Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iuriimattos/36a13129b104d233986be288fe85017b to your computer and use it in GitHub Desktop.
Save iuriimattos/36a13129b104d233986be288fe85017b to your computer and use it in GitHub Desktop.
My notes while studying for the OCP exam
ACP notes: https://gist.github.com/djangofan/a8b3e82e585525467c454515a8fb9ecf
Practice Tests $9.99: http://enthuware.com/index.php/ocpjp-8-average-scores
Guided Practice $140: http://www.ucertify.com/exams/Oracle/1Z0-809.html
Transcender: https://www.transcender.com/premium-solution/oracle/1z0-809.kap
Remember: javac -Xprint package.classname
https://ocpjava.wordpress.com/presentations/
http://www.java2s.com/Tutorials/Java/java.util.stream/Collectors/ !! STUDY THIS!!!
https://github.com/eugenp/tutorials/tree/master/core-java
https://www.slideshare.net/ibrahimkurce/oca-java-se-8-exam-chapter-6-exceptions
https://docs.oracle.com/javase/8/docs/api/java/util/function/class-use/BiPredicate.html
http://www.baeldung.com/java8
http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#MutableReduction - Collectors can be safe on parallel stream even when used with non-current collector: example: Collectors.toSet
Buy the Oracle OCP 1000 practice question book and you get access to online exam prep: https://testbanks.wiley.com/WPDACE/Login
OCA study guide practice tests: http://sybextestbanks.wiley.com/
Buy Enthuware exams: http://enthuware.com/ ; http://webets-server-aws.enthuware.com/webets.html
WHY GET THE EXAM?
--------------
1. To be a good "Java programmer", to be efficient, and to be fast, then memorization of Java API and fundamentals is necessary.
2. Taking the time to get this certification is a clear signal of what my goals are and what I want to do with my career.
3. This certification covers 30% more material than the 1.7 cert. People who don't have this certificate, mis-understand how difficult it is.
4. Having the cert proves attention to detail, ability to learn, and organizational skills.
5. Having this certification should enable me to be able to answer Java questions of any kind in a job interview.
6. This certification gives me a strong foundation for deeper exploration in other areas like functional programming, Spring, data/IO work, etc.
7. This certification is only the beginning of my growth. Achieving this allows me to set a higher goal to reach.
Also:
- Over 87% agree that Oracle Certification enhances their professional credibility.
- 84% of certified students have seen their job prospects improve.
- Over 70% say that Oracle Certification improved their earning power.
- More than 83% find themselves to be more productive in their jobs.
- Nearly 90% of students say they’re able to provide a higher level of service.
- 80% of students confirm that Oracle Certifications help them tackle complex issues & projects.
PAGES WITH GOOD INFO
-------------
https://www.mkyong.com/java8/java-8-collectors-groupingby-and-mapping-example/
My Repls: https://repl.it/user/djangofan OR https://repl.it/@djangofan
http://www.baeldung.com/java-fork-join
http://www.concretepage.com/java/jdk-8
http://docs.oracle.com/javase/specs/jls/se8/html/index.html
https://leetcode.com/?cong=true
WHAT TO LEARN AFTER I CERTIFY?
--------------
1. Create a Grid Chart UI: using something like https://masonry.desandro.com/ or https://github.com/ademilter/bricklayer
2. Clojure for the Brave And True (run Minerva, learn how it works)
a. explore Vase, Datomic
3. Spring JDBC / Singleton DataSource
4. SimpleReact NIO and CompleteableFuture: http://jroller.com/ie/entry/non_blocking_rest_calls_with
https://www.infoq.com/articles/Functional-Style-Callbacks-Using-CompletableFuture
5. Practice Mockito
6. Learn more about JDBC DataSource class
7. App environment JNDI
9. Explore StreamEx project
10. Get to know Observables better
11. Explore polyglot: http://vertx.io/ and https://deanwampler.github.io/polyglotprogramming/papers/
12. Re-read design pattern book.
13. CSV import batch job example: https://spring.io/guides/gs/batch-processing/
MY NOTES
-------------------------
For Enums, when comparing equality:
== is subject to type compatibility check at compile time
== will never throw NullPointerException
class Bond // does not implement Serializable
{
String ticker = "bac"; double coupon = 8.3; java.util.Date maturity = new Date();
}
class Portfolio implements Serializable
{
String accountName;
transient Bond[] bonds = new Bond[]{ }; // must be transient because Bond class does not implement Serializable
private void writeObject(ObjectOutputStream os) throws Exception{
os.defaultWriteObject();
os.writeInt(bonds.length);
//write the state of bond objects
for(int i=0; i<bonds.length; i++) {
os.writeObject(bonds[i].ticker);
os.writeDouble(bonds[i].coupon);
os.writeObject(bonds[i].maturity);
}
}
private void readObject(ObjectInputStream os) throws Exception{
os.defaultReadObject();
int n = os.readInt();
this.bonds = new Bond[n];
//read the state of bond objects.
for(int i=0; i<bonds.length; i++) {
bonds[i] = new Bond();
bonds[i].ticker = (String) os.readObject();
bonds[i].coupon = os.readDouble();
bonds[i].maturity = (java.util.Date) os.readObject();
}
}
}
abstract class Widget {
String data = "data";
public void doWidgetStuff() {
}
}
class GoodWidget extends Widget{
String data = "big data"; // this.data locates this value from the class instance, implicitly
public void doWidgetStuff() {
System.out.println(data);
}
}
public class WidgetUser{
public static void main(String[] args) {
Widget w = new GoodWidget();
w.doWidgetStuff(); // prints "big data"
System.out.println(w.data);// prints "data", value from reference
}
}
When using Object .wait method:
IllegalMonitorStateException: This exception is thrown if it is not called in a synchronized block.
import java.util.*;
import java.util.function.*;
class Account {
private String id;
public Account(String id){ this.id = id; }
public String getId() { return this.id;}
public void setId(String id) { this.id = id; }
}
public class BankAccount extends Account{
private double balance;
public BankAccount(String id, double balance){ super(id); this.balance = balance;}
public double getBalance() { return this.balance;}
public void setBalance(double bal) { this.balance = bal; }
public static void main(String[] args) {
Map<String, Account> myAccts = new HashMap<>();
myAccts.put("111", new Account("111"));
myAccts.put("222", new BankAccount("111", 200.0));
BiFunction<String, Account, Account> bif =
(a1, a2)-> a2 instanceof BankAccount? new BankAccount(a1, 300.0): new Account(a1);
myAccts.computeIfPresent("222", bif);
BankAccount ba = (BankAccount) myAccts.get("222");
System.out.println(ba.getBalance()); // prints 300.0
}
}
private Inner class is a private member of Outer class and is not inherited in any subclass of Outer.
// takes int arg , returns a String
IntFunction<String> func1 = a -> "" + a;
System.out.println(func1.apply(5));
// takes a String arg, returns an int
ToIntFunction<String> i = (x)-> Integer.parseInt(x);
System.out.println(i.applyAsInt("2"));
Instant now = Instant.now();
Instant now2 = now.truncatedTo(ChronoUnit.DAYS);
System.out.println(now2);
TemporalUnit is an interface and ChronoUnit is a class that implements this interface and defines constants such as DAYS, MONTHS, and YEARS.
If an object has 2 fields: a and b
Then dont implement hashCode like this: return a+b;
NOTE: this would be ok: return a/2;
ConcurrentModificationException is thrown by the methods of the Iterator interfaces. It is thrown when, while one thread is iterating through a collection, another thread modifies the collection.
Ordered is not necessarily sorted but sorted is always ordered.
Given: ls.stream().max(Comparator.comparing(a->a)).get();
The lambda here doesnt do much. We need a .get to get the Optional value.
NOTE: Stream .max method takes a Comparator arg whereas the IntStream method does not.
Given:
interface Reader{
default void read(Book b){ }
void unread(Book b);
}
Observe, tricksy, this will trigger the real .read method, not the abstract .unread method:
Reader r = b->{
System.out.println("Reading book "+b.getTitle());
};
books.forEach(x->r.read(x));
given: stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs.moveToInsertRow()
rs.updateString(1, "111");
rs.updateRow();
updateRow is used when you are trying to update an existing row. If you call this method while the cursor is on the insert row, an SQLException will be thrown. Otherwise, use:
rs.insertRow();
Rule: If the equals() method returns true, then hashCode() for both the objects must return the same value.
Note that the reverse is not required.
Two of an object both returning same hashCode does not mean they are equal.
A JDBC try-with-resources doesn't require catch SQL Exception.
Duration d = Duration.ofMillis(1100);
System.out.println(d); //prints PT1.1S
Only non-terminal operations such as filter, peek, map, distinct, sorted, and skip are lazy. All terminal operations such as forEach, reduce, collect, count, min, max, allMatch, findAny are eager.
IntStream is1 = IntStream.range(1, 3);
IntStream is2 = IntStream.rangeClosed(1, 3);
IntStream is3 = IntStream.concat(is1, is2);
Object val = is3.boxed().collect(Collectors.groupingBy(k->k)).get(3); // {1=[1, 1], 2=[2, 2], 3=[3]}
System.out.println(val); // 3
A BufferedReader can only be created using a Reader such as FileReader. It cannot directly operate on a file.
Collectors .groupingBy can take 1,2, or 3 args. Collectors .mapping only takes 2 args: the functional ref and the collector type.
Useful: List<String> people = people.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList));
No such thing as Executors.getSingleThreadExecutor(); !! It should be Executors.newSingleThreadExecutor();
If a interface reference doesn't contain a method being called, the compiler will catch that error.
Be careful of stream .collect when its not assigned to anything on the left.
Considering a static initializer in a class:
The static block will be executed only once when the class is loaded. A class is loaded when it is first referenced, which is before the object may have been initialized.
Use ReentrantLock when you need to lock writes but still allow unlocked reads.
128 does not fit into a byte. It has a minimum value of -128 and a maximum value of 127 (inclusive).
char: The char data type is a single un-signed 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).
// relativize counts single dots like a double dot or a folder!!!
import java.nio.file.*;
class Main {
public static void main(String[] args) {
Path p1 = Paths.get("/personal/./photos/./readme.txt");
Path p2 = Paths.get("/personal/index.html");
Path p3 = p1.relativize(p2);
System.out.println(p3); //prints ../../../../index.html
}
}
There is no getValue method in ResourceBundle.
These are both valid calls on ResourceBundle:
Object obj = rb.getObject("key1");
String[] vals = rb.getStringArray("key2");
You cannot override a static method (in class or interface) with a non-static method and vice-versa. You can, however, redeclare a static method of a super interface as a default method in the sub interface.
Compiler wont know what type of object these args hold and you can add any object to these args. Compiler will show a warning. If People has a good .toString method, then you can add a people or a String and get the same result when printing:
public void helpPeople(Queue people, Queue helped)
https://repl.it/KtzJ/7
Trying to add non-Comparable items to TreeSet will fail at Runtime.
Remember that java.io.IOException is a superclass of all exceptions under java.nio.file package.
FileNotFoundException|IOException e is not valid
You need to provide generic implementation that can be overridden by the subclasses.
This doesn't require the class to be abstract. A regular base class can also achieve this.
Remember that transient fields and static fields are never serialized. Constructor, instance blocks, and instance field initialization of the class being deserialized are also not invoked. The following field would get re-initialized to 0:
transient int ti = 10;
A Map can contain itself as a value, not as a key. The Map .values method returns Collection (not Set). Map interface does not extend Collection interface.
java.util.NavigableMap extends Map and SortedMap
Duration counts in terms of hours, minutes, and seconds. Therefore, days are converted into hours. That is why the first println prints PT24H and not PT1D.
A Duration of 0 is printed as 0S and a Period of 0 is printed as 0D.
Assertions are appropriate to check whether method parameters are valid only on private methods.
When an assertion fails, a programmer should always allow code to throw the AssertionError rather than swallowing it.
new TestClass.A(); is same as new A() where A is a regular public inner class !!!
NOTE: notice here that we didnt say "new Builder()" because public static final class Locale.Builder :
Locale myloc = new Locale.Builder().setLanguage("en").setRegion("UK").build();
ResourceBundle msgs = ResourceBundle.getBundle("mymsgs", myloc);
NOTE2: yes, this will pick up keys from both mymsgs.properties and also mymsgs_en_UK.properties
Remember that static method of an interface can only be accessed by using the name of that interface. i.e. Boiler.shutdown()
new Locale("wh","WH") == Locale.WHATEVER
rb = ResourceBundle.getBundle("appmessages", Locale.CHINA);
rb = ResourceBundle.getBundle("appmessages", new Locale("ch", "CH"));
The Locale class provides a number of convenient constants that you can use to create Locale objects for commonly used locales. For example, the following creates a Locale object for the United States:
Locale.US
stmt.setMaxRows(2); // is ok
LocalDateTime ld1 = LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 0);
ZonedDateTime zd1 = ZonedDateTime.of(ld1, ZoneId.of("US/Eastern"));
LocalDateTime ld2 = LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 0);
ZonedDateTime zd2 = ZonedDateTime.of(ld2, ZoneId.of("US/Eastern"));
long x = ChronoUnit.HOURS.between(zd1, zd2);
System.out.println(x); // prints -2
//this is ok; var outside of function can accessible as part of supplier
String name = "bob";
Supplier<String> s = name::toUpperCase;
val = s.get();
PrintWriter .printf will return the PrintWriter back for chaining while .write will not.
// wont compile since IOException is unreachable
try{
pw.write(text);
}catch(IOException e){
System.out.println("exception in writing");
}
Note that none of the PrintWriter's methods throw any I/O exceptions because they supress the errors in writing and set an internal flag for error status instead.
The checkError method returns true if there has been a problem in writing.
f.getParentFile() will return a File Object representing c:\a\b\c\d
getParent() returns a String and getParentFile() returns a File object
enum Pets {
String name;
DOG("D"), CAT("C"), FISH("F"); // BAD placement
Pets(String s) { name = s;}
}
Enum constants (here, DOG, CAT, and FISH) must be declared before anything else.
enum Pets {
DOG("D"), CAT("C"), FISH("F");
static String prefix = "I am ";
String name;
Pets(String s) { name = prefix + s;} // BAD
public String getData(){ return name; }
}
Unlike a regular java class, you cannot access a non-final static field from an enum's constructor.
UnaryOperator<String> uo = str->str.toUpperCase();
letters.replaceAll(uo);
letters.forEach(System.out::print);
The replaceAll method replaces each element of this list with the result of applying the operator to that element. str->str.toUpperCase() is a valid lambda expression that captures UnaryOperator function.
The forEach method performs the given action for each element of the Iterable until all elements have been processed by feeding each element to the given Consumer. System.out::print is a valid method reference that can be used to create a Consumer instance.
List's void replaceAll(UnaryOperator<E> operator) : is a mutable alteration
public static Stream<Path> find(Path start, int maxDepth, BiPredicate<Path,BasicFileAttributes> matcher, FileVisitOption... options) throws IOException
Map's forEach method requires BiConsumer object
None of the calls to Console throw any checked exception.
Call to System.console() doesn't throw any exception either. It just returns null if Console is not available.
Remember that the readLine and readPassword methods of Console do not declare any checked exceptions. Therefore, calls to these methods need not be wrapped in a try block or declared in the throws clause of the calling method.
Map<String, Integer> map1 = new HashMap<>();
map1.put("a", 1);
map1.put("b", 1);
map1.merge("b", 1, (i1, i2)->i1+i2);
map1.merge("c", 3, (i1, i2)->i1+i2);
System.out.println(map1); //prints {a=1, b=2, c=3}
ComplicatedAction newtask1 = new ComplicatedAction(ia, from, mid);
ComplicatedAction newtask2 = new ComplicatedAction(ia, mid+1, to);
newtask2.fork();
newtask1.compute();
newtask2.join();
// also abstract class
public abstract class ForkJoinTask<V> extends Object implements Future<V>, Serializable
// not an interface!
public abstract class RecursiveAction extends ForkJoinTask<Void>
You cannot do this:
TreeSet<Integer> s = new TreeSet<Integer>();
TreeSet<Integer> subs = new TreeSet<Integer>();
for(int i = 324; i<=328; i++){
s.add(i);
}
subs = (TreeSet) s.subSet(326, true, 328, true );
subs.add(329); //cant add to a TreeSet subset outside of its inclusive range
// NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)
Wont compile: String pwd = c.readPassword(..)
This is ok: char[] pwd = c.readPassword(..)
final String a = "A";
final int b = 10;
console.readLine("With string %s and a formatted number %.2f", a, b);
Will output "With string A and a formatted number 10.00" onto the prompt.
Methods that do not modify the collection (i.e. the threads that just "read" a collection) should acquire a read lock and threads that modify a collection should acquire a write lock.
Optional's orElseGet method takes a java.util.function.Supplier function as an argument
Optional's orElse can take a non-function parameter
No such thing as .ofNullable(Supplier)
The auto-closeable variables defined in the try-with-resources statement are implicitly final. Thus, they cannot be reassigned.
Use con.setAutoCommit(false);
with con.commit();
This is a proper declaration of a Comparator, used in Collections.sort(l, c)
Collections.sort(al, new Comparator<Person>(){
public int compare(Person o1, Person o2) {
return o1.dob.compareTo(o2.dob);
}
});
deserialization would include these variables:
final static String f4 = "4";
static String f3 = "4";
String var = 6;
Instant class does not have public constructors. You create Instant objects by using it static helper methods such as Instant.now() or by using existing Instant objects, for example: Instant newInstant = oldInstant.plusSeconds(1);
All classess in java.time package such as classes for date, time, date and time combined, time zones, instants, duration, and clocks are immutable and thread-safe.
Only classes that are explicitly designed to work with time zones (such as ZonedDateTime, OffsetDateTime, and OffsetDate ) incorporate the time zone. All other classes such as Instant , LocalDate, LocalTime, Period, and Duration do not have any time zone.
assert v.size() == 10 : v;
Valid because <boolean_expression> : <any_expression_but_void> is satisfied.
assert v.size() == 10 : v.clear();
Invalid because List.clear() returns void and boolean : void does not satisfy <boolean_expression> : <any_expression_but_void>, which is required for an assert statement
flatMapToDouble requires a function that returns a DoubleStream and not just a double. for example:
row -> Arrays.stream(row.getLuckyNum())
country (not region!!) is the second parameter that may be passed while creating a Locale. It is not required though.
If a HashMap already contains an entry for the specified key, the element already in this dictionary for that key is returned after modifying the entry to contain the new element.
The implementation details are not known at the time.
This is a valid reason for declaring an interface but not an abstract class. Generally, the purpose of an interface is to identify and declare just the behavior. Actual implementation can come later. While abstract class is used when a common implementation is also identified. In that respect, an abstract class actually provides less abstraction than an interface.
BufferedWriter's append method = works same as the write(String) method. It doesn't really append the data to the end of the existing content. It overwrites the existing content. If you need to append, you use write(String,true)
If you have this: A a = new B();
Where A has a protected instance var i and B extends A
Then, B cannot access A.i because A's i does not have membership in B . When B is created, it might have a B.i var, but once you assign a A reference to the B object, then accessibility of the i is no longer there. This only happens between different packages. Same thing with methods
This will print: 10.0 12.0
List<Double> dList = Arrays.asList(10.0, 12.0);
dList.stream().forEach(x->{ x = x+10; });
dList.stream().forEach(d->System.out.println(d));
NOTE: if the List contained mutable objects, rather than Number, then the value of references would have changed.
The actual classes for Connection, Statement, and ResultSet interfaces are provided by the JDBC driver and are therefore driver dependent.
The RowSet interface extends the standard java.sql.ResultSet interface and is implemented as part of JDBC driver.
ResultSet has a get by column name method: rs.getInt("GPA")
Must map to IntStream/DoubleStream from a stream before trying to use .sum() method:
double sum = ls.stream().mapToInt(x->x).sum();
There no sum method in Stream. There is one in IntStream and DoubleStream.
You can redeclare a static method of a super interface as a non-static default method in the sub interface.
Test might show a question about enabling assertions where the answer doesn't use it.
Remember that StringBuilder and StringBuffer do not extend String. Be careful with this in functional interfaces and lambdas.
public void set(E o) {
lock.lock();
try {
i++;
list.add(o);
System.out.println("Adding element by thread" + Thread.currentThread().getName());
} finally {
lock.unlock();
}
}
Lock.lock() returns void. Lock.tryLock() returns boolean.
Had the code been:
ReentrantLock rlock = new ReentrantLock();
boolean f1 = rlock.tryLock();
System.out.println(f1);
boolean f2 = rlock.tryLock();
System.out.println(f2);
It would have printed: true true
Note: that ReentrantLock implements Lock.
An important point to understand with method or constructor references is that you can never pass arguments while referring to a constructor or a method. Remember that such references are mere references. They are not actual invocations.
Given this class, you can create a new object with a functional interface in 2 ways!!!
class MyProcessor {
int value;
public MyProcessor(){ value = 10; }
public MyProcessor(int value){
this.value = value;
}
public void process(){
System.out.println("Processing "+value);
}
}
Supplier<MyProcessor> supp = MyProcessor::new;
MyProcessor mp = supp.get();
mp.process();
Function<Integer, MyProcessor> f = MyProcessor::new;
MyProcessor mp = f.apply(10);
mp.process();
getDuplicateHolder is a method and not a constructor. Therefore, you cannot specify generic type on the right hand side in this manner: PlaceHolder<String, String> ph2 = PlaceHolder<String>.getDuplicateHolder("b");
You can do the following:
PlaceHolder<String, String> ph1 = PlaceHolder.<String>getDuplicateHolder("b");
For Path .resolveSibling(other): If this path does not have a parent path, or other is absolute, then this method returns other.
1. relativize method does not take a String as an argument. It takes a Path object.
2. relativize method is meant to convert an absolute path into a relative path.
Stream<Path> lines = Files.list(Paths.get("c:\\temp\\test.txt"));, it will compile but will throw java.nio.file.NotDirectoryException because test.txt is not a directory.
List<String> lines = Files.readAllLines(Paths.get(uri), Charset.defaultCharset());
There is no readLines() method in any Java class.
The Collector created by Collectors.toMap throws java.lang.IllegalStateException if an attempt is made to store a key that already exists in the Map.
Input params of a private method can be validated using assertions but NOT public methods.
Its ok if lambda expression passes primitive arg:
Doer d = (int a, String b)->b.substring(0, a);
The synchronized keyword cannot be applied to a abstract method. Synchronized implies there is a inner synchronized body.
When overriding .equals(Object) and/or .hashCode(), this doesn't mean the class needs to implement comparable to be used in a HashSet. This is distinct from Comparators .equals(Object, Object) method.
Using a ExecutorCompletionService.poll/take, you are receiving the Futures as they finish, in completion order (more or less). Using ExecutorService.invokeAll, you do not have this power; you either block until are all completed, or you specify a timeout after which the incomplete are cancelled.
Generates numbers 1-10 randomly:
int r = ThreadLocalRandom.current().nextInt(1, 11);
int r = (int)(Math.random()*10);
Demonstration of lock.readLock().lock();
https://repl.it/Kgm6/6
Here are a few important things you need to know about Optional class:
1. Optional has a static method named of(T t) that returns an Optional object containing the value passed as argument. It will throw NullPointerException if you pass null. If you want to avoid NullPointerException, you should use Optional.ofNullable(T t) method. This will return Optional.empty if you pass null.
2. You cannot change the contents of Optional object after creation. Optional does not have a set method. Therefore, grade.of, although technically correct, will not actually change the Optional object referred to by grade. It will return a new Optional object containing the passed argument.
3. The orElse method returns the actual object contained inside the Optional or the argument passed to this method if the Optional is empty. It does not return an Optional object. Therefore, print(grade1.orElse("UNKNOWN")) will print UNKNOWN and not Optional[UNKNOWN].
4. isPresent() returns true if the Optional contains a value, false otherwise.
5. ifPresent(Consumer ) executes the Consumer object with the value if the Optional contains a value. Not that it is the value contained in the Optional that is passed to the Consumer and not the Optional itself.
Optional<String> grade = Optional.empty();
grade.of("WHATEVER");
You cannot change the contents of Optional object after creation. Optional does not have a set method. Therefore, grade.of, although technically correct, will not actually change the Optional object referred to by grade. It will return a new Optional object containing the passed argument. Similar to DateTime .of methods.
java.io.InvalidClassException is for Serialization and extends IOException (checked).
NavigableMap<String, String> mymap = new TreeMap<String, String>();
mymap.put("a", "apple"); mymap.put("b", "boy"); mymap.put("c", "cat");
mymap.put("aa", "apple1"); mymap.put("bb", "boy1"); mymap.put("cc", "cat1");
NavigableMap<String, String> tailmap = mymap.tailMap("bb", false); //contains c and cc
public void m1(List<? extends Number> list)
{
list.add(new Integer(10)); //Error at compile time because the compiler
//only knows that list contains Number or its subclass objects. But it doesn't know the exact type.
//Therefore, it will not allow you to add anything to it.
Number n = list.get(1); //This will work because the compiler knows that every object in list IS-A Number.
}
The "get-put" principle:
If you get something from a parametrized container, use extends. Such as on a getter method definition.
If you put something into a parametrized container, use super. Such as a List<? super String> .
The lower bound "super" bound is not allowed in class definition but upper-bound extends is:
//this code does not compile !
class Forbidden<X super Vehicle> { }
// this is ok
class BST<X extends Comparable<X>> {}
This Map is read-only:
Map<Object, ?> m = new LinkedHashMap<Object, Object>();
But this one is mutable:
Map<Object, Object> m = new LinkedHashMap<Object, Object>();
Also, a compile error if you try to put something in this:
Map<Object, ? super ArrayList> m = new LinkedHashMap<Object, ArrayList>();
List<? super Honda> means that it could, in fact, be a List<Honda>. It could be a List<Vehicle> as well, but you don't know that. As far as adding goes, it IS a List<Honda>.
If you want to be able to add Vehicles, you need to declare the list to allow Vehicles:
- List<Vehicle>
- List<? super Vehicle> //is mutable
- List<Object> // equals List<? super Object>
That will still allow Civics and Hondas though.
Upper bounded wildcards or unbounded wildcards are generally read-only
Lower bounded wildcards are generally mutable
With a lower-bound wildcard, List<? super String>, we could add String or any superclass of String because we know that supertype references are ok.
List< ? super Car > carList = new ArrayList<Car>();
carList.add(new Car()); // Ok, is mutable
carList.add(new Vehicle()); // Compile-time Error
Given:
class Outsider {
public class Insider{ }
}
public class TestClass {
public static void main(String[] args) {
Outsider os = new Outsider();
// 1 insert line here
}
}
Outsider.Insider in = os.new Insider();
- Since Insider is not a static class, it must have an associated outer class instance.
BAD: Insider in = Outsider.new Insider();
- You cannot refer to Insider class directly. You must use Outsider.Insider to declare the type of variable in.
- Outsider.new Insider() is wrong as well because Insider is not static. Further, even if Insider were static, the syntax to instantiate it would be: new Outsider.Insider().
For Collections.sort(List ) method to work, the elements of the passed List must implement Comparable interface. If the List is a generic type the compiler will detect the error. If the type is not a generic, then it wont be caught until runtime.
Questions will try to trick you into thinking Thread was started when you didn't call .start
This is valid code but will produce warning at compile time:
Map<String , List<? extends CharSequence>> stateCitiesMap = new HashMap();
List<Book> books = Arrays.asList(
new Book("Freedom at Midnight", 5.0),
new Book("Gone with the wind", 5.0),
new Book("Midnight Cowboy", 15.0)
);
// yes, this next line will modify 1 item in the List. A stream gives you a modifyable view to the list you streamed from.
books.stream().filter(b->b.getTitle().startsWith("F")).forEach(b->b.setPrice(10.0));
books.stream().forEach(b->System.out.println(b.getTitle()+":"+b.getPrice()));
Usually use a BiConsumer on a Map stream function
List<String> names = Arrays.asList("Peter", "Paul", "Pascal");
Optional<String> ops = names.stream()
.parallel()
.allMatch(name->name!=null) // terminal operation!! no more chaining!!
.filter(name->name.length()>6)
.findAny();
System.out.println(ops);
.findAny
This is a valid terminal operation but is not considered a reduction operation.
Given:
Comparator<Book> c1 = (b1, b2)->b1.getGenre().compareTo(b2.getGenre());
books.stream().sorted(c1.thenComparing(Book::getTitle));
- public <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor) : This method uses the supplied Function to get a value from the objects to be compared and then compares that value. The value returned by the function must be Comparable. thenComparing can also take a Comparator arg instead of the "comparable supplier".
This will throw FileSystemNotFoundException on linux: Path p1 = Paths.get(new URI("file://e:/temp/records"));
You can pass Properties object o jdbc connection:
Properties p = new Properties();
p.setProperty("user", userid);
p.setProperty("password", pwd);
Connection c = DriverManager.getConnection(dburl, p);
To fully understand binary search: https://repl.it/Kg1M/19
All about probem with upper-bounded wildcard: https://repl.it/KgYp/31
// If the Predicate parameter is specified on left side of lambda as any object other than Object, make sure reference declares it! Predicate without
These are equivalent:
Predicate<Integer> even = (Integer i)-> i%2==0;
Another option is to used Object type like this:
Predicate even = (Object i)-> ((Integer)i)%2==0;
or
Predicate even = i -> ((Integer)i)%2==0;
Be careful calling methods from a method reference when the reference doesn't contain the method hook that exists in the actual object.
Remember that variables are not overridden. They are hidden or shadowed and it is ok for a subclass to hide a variable defined in the base class, even if its final.
Just like java.io.File, this won't throw an exception if the file does not exist unless you try to operate on it:
Path p1 = Paths.get("c:\\temp\\test1.txt");
When overriding this method: public void robustMethod(int[] intArray) throws AssertionError
- When extending a method: any Error or RuntimeException can be thrown without having to declare them in the throws clause.
- Throwable is a super class of AssertionError so it cannot be thrown from the subclass's overriding method.
- Throwable-->Exception is in a different branch of Exceptions than Throwable-->Error-->AssertionError. So, dont extend method with 'throws Exception'.
A Duration can hold more than 24 hours: PT25H
The equals() method must be reflexive i.e. x.equals(x) should return true.
If the file already exists, it will be overwritten with a new file. To append to the existing file, the following constructor should be used.
public FileWriter(String fileName, boolean append)
When you use SQL .rollback, if you don't pass a SavePoint to it, then it will rollback the whole uncommitted transaction.
SQL to print all column names with their values for all rows in the result set:
Connection c = DriverManager.getConnection("jdbc:derby://localhost:1527/sample", "app", "app");
try(Statement stmt = c.createStatement();) {
ResultSet rs = stmt.executeQuery("select * from STUDENT");
ResultSetMetaData rsmd = rs.getMetaData();
int cc = rsmd.getColumnCount();
while(rs.next()) {
for (int i = 1; i<=cc; i++) {
System.out.print(rsmd.getColumnName(i)+" = "+rs.getObject(i)+", ");
}
System.out.println();
}
} catch(SQLException e) {
e.printStackTrace();
}
Package, remember:
java.nio.file.NoSuchFileException: test.txt
Note that java.io.FileNotFoundException may be thrown by java.io.FileInputStream, FileOutputStream, and RandomAccessFile constructors if the file by the given name does not exist.
Outer.this.data is ok to access a var from a Inner.class
// even if .between args are swapped, it always prints positive value PT3H
LocalDateTime ldt = LocalDateTime.of(2017, 12, 02, 6, 0, 0);
ZonedDateTime nyZdt = ldt.atZone(nyZone);
ZonedDateTime laZdt = ldt.atZone(laZone);
Duration d = Duration.between(nyZdt, laZdt);
System.out.println(d);
PrintWriter: Prints formatted representations of objects to a text-output stream. You can pass a OutputStream OR a Writer into the constructor of PrintWriter!
OutputStreams are meant for binary data. Writers (including PrintWriter) are meant for text data.
PrintWriter suppresses IOExceptions: it only throws an exception if a File object you pass to it has an exception thrown.
DataOutputStream provides methods such as writeInt, writeChar, and writeDouble, for writing complete value of the primitives to a file. So if you want to write an integer to the file, you should use writeInt(1)
You can read back the stored primitives using methods such as DataInputSream.readInt().
PrintWriter can write primitives but the method names are: print(int), print(boolean), print(long)
Be aware of static method references: https://repl.it/Kesh/15
slist.stream().forEach(Student::debug); // this works when .debug method is not static.
On a switch statement using Enum:
switch(s) {
case OFF : System.out.println("It is off!"); break;
}
Don't do This:
switch(s) {
case SwitchEnum.OFF : System.out.println("It is off!"); break;
}
Watch out for Optionals that don't first as for .isPresent!
Why is Thread.stop deprecated?
- Because it is inherently unsafe. Stopping a thread causes it to unlock all the monitors that it has locked.
Concerning Deque questions:
- All Deque objects have all the Queue methods because Queue is the super-interface
- pollFirst()/pollLast() - poll is a Queue method. Therefore pollFirst and pollLast will remove elements from the front and from the end respectively.
- removeFirst()/removeLast() - These are Deque specific methods. They will remove elements from the front and from the end respectively. These methods differ from pollFirst/pollLast only in that they throw an exception if this deque is empty.
- offerFirst(e)/offerLast(e) - offer is a Queue method. Therefore offerFirst and offerLast will add elements to the front and to the end respectively.
- addFirst(e)/addLast(e) - add is a Queue method. Therefore addFirst and addLast will add elements to the front and to the end respectively.
- peek(), peekFirst(): return the first element from the front of the queue but does not remove it from the queue.
- peekLast() : returns the last element from the end of the queue but does not remove it from the queue.
- element(): retrieves, but does not remove, the head of the queue represented by this deque (in other words, the first element of this deque). This method differs from peek only in that it throws an exception if this deque is empty.
- Notice that there is no such thing as Stack method pushFirst(e) and pushLast(e) on Deque.
However, stdout and stderr can be redirected to different places. For instance, output can be redirected to a file while error messages still appear on the console. This can break your ability to get an instance of System.console()
Some candidates have reported getting a question that expects you to know about ClassNotFoundException and NoSuchFieldException.
Both of these are checked exceptions and are thrown when you use Java reflection mechanism to load a class and access its fields.
BOTH are Checked exceptions! I would have guessed Runtime:
Class c = Class.forName("test.MyClass"); //may throw ClassNotFoundException
java.lang.reflect.Field f = c.getField("someField"); //may throw NoSuchFieldException
collection by using collect() or toArray() methods. These methods are categorize as mutable reduction because it collects desired result into a mutable object such as a Collection.
BinaryOperator<String> bo = (s1, s2) -> s1.concat(s2);
List<String> names = new ArrayList<>();
names.add("Bill"); names.add("George"); names.add("Obama");
String finalvalue = names.stream().reduce("Hello : ", bo);
System.out.println(finalvalue); // prints 'Hello : BillGeorgeObama'
Given: public static <E extends CharSequence> List<? super E> doIt(List<E> nums)
- The input parameter has been specified as List<E>, where E has to be some class that extends CharSequence. So ArrayList<String>, List<String>, or List<CharSequence> are all valid as reference types for 'in'.
- The output type of the method has been specified as List<? super E> , which means that it is a List that contains objects of some class that is a super class of E. Here, E will be typed to whatever is being used for 'in'. For example, if you declare ArrayList<String> in, E will be String.
- The important concept here once the method returns, there is no way to know what is the exact class of objects stored in the returned List. So you cannot declare out in a way that ties it to any particular class, not even Object.
- Thus, the only way to accomplish this is to either use non-typed reference type, such as: List result; or use the same type as the return type mentioned in the method signature i.e. List<? super String> (because E will be bound to String in this case.)
Yes, you can override the .run method of a Thread object with synchronized modifier.
// Given Filename: TestClass.java
class TestClass implements T1, T2{
public void m1(){}
}
interface T1{
int VALUE = 1;
void m1();
}
interface T2{
int VALUE = 2;
void m1();
}
Having ambiguous fields or methods does not cause any problems by itself but referring to such fields/methods in an ambiguous way will cause an error at compile time. So you cannot call : System.out.println(VALUE); because it will be ambiguous (there are two VALUE definitions). But the following lines are valid :
TestClass tc = new TestClass();
System.out.println(( ( T1) tc).VALUE);
However, explicit cast is not required for calling the method m1() :
( ( T2) tc).m1();
tc.m1() is also fine because even though m1() is declared in both the interfaces, the definition to both resolves unambiguously to only one m1(), which is defined in TestClass.
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Main {
public static void main(String[] s) {
Map<String, Boolean> whoLetDogsOut = new ConcurrentHashMap<>();
whoLetDogsOut.computeIfAbsent("snoop", k -> f(k));
whoLetDogsOut.computeIfAbsent("snoop", k -> f(k));
}
static boolean f(String s) {
System.out.println("creating a value for \""+s+'"'); // prints only 1 item
return s.isEmpty();
}
}
Given 1.7 code:
Map<String, List<Double>> groupedValues = new HashMap<>();
public void process(String name, Double value){
List<Double> values = groupedValues.get(name);
if(values == null){
values = new ArrayList<Double>();
groupedValues.put(name, values);
}
values.add(value);
}
With a Lambda:
public void process(String name, Double value){
groupedValues.computeIfAbsent(name, (a)->new ArrayList<Double>()).add(value);
// computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
}
The objective of the given code is to collect multiple values for a given key in a map. When a value for a new key is to be inserted, it needs to put a List in the map first before adding the key to the List.
- computeIfAbsent is perfect for this. This methods checks if the key exists in the map. If it does, the method just returns the value associated with that key. If it doesn't, the method executes the Function, associates the value returned by that Function in the map with that key, and returns that value.
Thus, for example, If your Path is "c:\\code\\java\\PathTest.java",
p1.getRoot() is c:\ ((For Unix based environments, the root is usually / ).
p1.getName(0) is code
p1.getName(1) is java
p1.getName(2) is PathTest.java
p1.getName(3) will cause IllegalArgumentException to be thrown (not IndexOutOfBoundsException)
Durations and periods differ in their treatment of daylight savings time when added to ZonedDateTime. A Duration will add an exact number of seconds, thus a duration of one day is always exactly 24 hours. By contrast, a Period will add a conceptual day, trying to maintain the local time.
Remember:
newtask1.fork(); // fork separate thread into the unknown
int x = newtask2.compute(); //current thread do work
int y = newtask1.join(); //once compute is done, ask for result of newTask1
A ForkJoinPool differs from other kinds of ExecutorService mainly by virtue of employing work-stealing!!
What this really means is that if worker thread is done with a task, it will pick up a new task irrespective of which thread created that task. In a fork/join framework, any worker thread may spawn new tasks and it is not necessary that the tasks spawned by any threads will be executed by that particular thread. They can be executed by any available thread.
The number of threads created depends on how the ForkJoinPool is created. By default, it uses the number processors available.
CopyOnWriteArrayList guarantees that the Iterator acquired from its instance will never get this exception. This is made possible by creating a copy of the underlying array of the data. The Iterator is backed by this duplicate array.
An implication of this is that any modifications done to the list are not reflected in the Iterator and no modifications can be done on the list using that Iterator (such as by calling iterator.remove() ). Calls that try to modify the iterator will get UnsupportedOperationException.
The List forEach method requires a method that takes an argument: void forEach(Consumer<? super T> action)
A single threaded executor getting 3 Callable tasks will run those tasks in the same thread:
https://repl.it/Kdx0/4
Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.
A thread can obtain locks of multiple object by nesting synchronized blocks. For example,
synchronized(obj1){
synchronized(obj2) {
//here the thread has locks of obj1 as well as obj2
}
}
Also remember that Java does not have any mechanism to prevent deadlocks. It is up to the developer to use the locks correctly to avoid deadlocks. One strategy that is commonly used to prevent deadlocks is to always acquire locks of the objects in the same sequence. (This topic will be elaborated in other questions.)
Please go through this link that explains synchronization and intrinsic locks. You will find questions in the exam that use statements given in this trail: https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
Java lambdas are not required to use a functional interface spec. For example:
With a static isFiction method in a static BookFilter inner class, this will work:
.filter((Book b)->Book.BookFilter.isFiction(b))
I think a functional interface, implementing Predicate<Book>, and implementing .test method would allow you to do something like this:
The method reference (Book.BookFilter::isFiction) is semantically the same as the lambda expression :
(Book b) -> Book.BookFilter.isFiction(b)
You may also do it without making the method static as follows:
.filter(new Book.BookFilter()::isFiction)
NOTE: usage here of new Book.BookFilter() to create instance of static class:
You have to have a reference to the other outer class as well:
Inner inner = new MyClass().new Inner();
If Inner was static then it would be:
Inner inner = new MyClass.Inner();
Multiple copies of an object may be added to a file stream.
The statement is a bit vague: It is trying to convey that the same object can be serialized multiple times to a ObjectOutputStream stream. Thus, you may have mutliple copies of the same object in the stream and when you read the stream back, you will get multiple objects back.
Suppressed exception example: https://repl.it/Kdvu/4
count, forEach, sum, allMatch, noneMatch, anyMatch, findFirst, and findAny are terminal Stream operations.
2 threads can be synchronized on the same Runnable instance:
https://repl.it/KdvN/4
NoSuchFileException is a subclass of IOException. In the same multi-catch block, you cannot include classes that are related by inheritance.
Remember that BufferedReader.close (which is called automatically at the end of the try-with-resources block) and BufferedReader.readLine methods throw java.io.IOException.
A synchronized method is similar to any other method except that only one thread can be in it at a given time.
A thread can reacquire a lock. This means once it enters a synchronized method sm1() it can call any other synchronized method within it.
A thread can enter a synchronized method only after it acquires a lock.
A thread is allowed to reacquire a lock that it already has. So there will not be a deadlock if a method calls itself.
Interfaces used by lambda expressions should have 1 abstract method in the interface. Not default. Not static either.
FileInputStream has a read(#ofbytes) method that reads multiple bytes like a BufferedInputStream would do. So, im not entirely sure the advantage of BufferedInputStream except that its much faster when the read blocks are smaller chunks. Reading giant file chunks might be faster without it... just reading file data direct into memory array.
List<Integer> ls = Arrays.asList(3,4,6,9,2,5,7);
System.out.println(ls.stream().reduce(Integer.MIN_VALUE, (a, b)->a>b?a:b)); //9
System.out.println(ls.stream().max(Integer::max).get()); //3
System.out.println(ls.stream().max(Integer::compare).get()); //9
System.out.println(ls.stream().max((a, b)->a>b?a:b)); //Optional[3]
This code prints: file:///c:/temp/test.txt
Path p1 = Paths.get("c:\\..\\temp\\test.txt");
System.out.println(p1.normalize().toUri());
When putting objects in HashMap: Now, if you do not implement the hash code, object class's hashcode will be used. So when you put the original Book object, its hash code will be different from the book object that you pass in get(book). Thus, it will not find the right bucket and so it will not be able to find the original book object.
// Be aware of this error: https://repl.it/KdTq
Main.java:26: error: illegal static interface method call
System.out.println(off.getAddress()); //2
the receiver expression should be replaced with the type qualifier 'Office'
Call .start on a Thread object, not a Runnable!
ArrayDeque is also like a Stack and has a pop method.
Files.move has a ATOMIC_MOVE option, which uses the default file system behavior or throws exception.
Queue<Request> container = new Queue<Request>();
Queue is an interface so it cannot be instantiated. PriorityQueue is a class that implements Queue.
Assertions should be liberally used to ensure the assumptions that you have made while coding hold true.
java.lang.Object .wait method can throw IllegalMonitorStateException
This exception is thrown if it is not called in a synchronized block.
An outer class can access private inner class members.
int x = ai.incrementAndGet();
The ai.incrementAndGet method atomically increments the current value by 1 and returns the new value. Therefore, 5 will be incremented by 1 to 6 and 6 will be returned.
int x = ai.addAndGet(1);
The addAndGet method atomically adds the given value to the current value and returns the new value. Here, we are passing 1. So 1 will be added to 5 and 6 will be returned.
Concerning IntFunction:
It takes Integer parameter and returns a String. It can be parameterized to return any thing. For example:
IntFunction<String> f = x->""+x; //returns a String.
int to String
When using a array object of primitives and streaming it, the function package contains primitive specialized versions of streams as well as functional interfaces. For example, instead of using Stream<Integer>, you should use IntStream. You can now process each element of the stream using IntFunction. This will avoid auto-boxing/unboxing altogether.
Also, this returns a int primitive, taking a String parameter :
String to int
ToIntFunction<String> i = (x)-> Integer.parseInt(x);
System.out.println(i.applyAsInt("2"));
Remember that HashMap supports adding 1 null key as well as null values but ConcurrentHashMap does not.
The main reason that nulls aren't allowed in ConcurrentMaps (ConcurrentHashMaps, ConcurrentSkipListMaps) is that ambiguities that may be just barely tolerable in non-concurrent maps can't be accommodated. The main one is that if map.get(key) returns null, you can't detect whether the key explicitly maps to null vs the key isn't mapped. In a non-concurrent map, you can check this via map.contains(key), but in a concurrent one, the map might have changed between calls.
The order of elements seen while iterating through a HashSet always remains same: It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time.
All the classes of java.time package are immutable and thread-safe. The old java.util.Date and time classes of java.util weren't thread safe.
You cannot create an instance of Instant using new Instance(). You create an instance using static methods Instant.now() or Instant.now(Clock ).
Instant.now() will return the time as of UTC, while LocalDateTime.now() will return the time as per the time shown by the operating system clock, which depends on the time zone. For example, see the following code and its output if it is run in India (which is 5.30 hrs ahead of UTC) at 7.30 PM:
Instant ins = Instant.now();
System.out.println(ins); //prints 2017-01-20T14:00:00.000Z
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);//prints 2017-01-20T19:30:00.000 Notice that there is no Z at the end
Note: that from the above output, it may look like LocalDateTime has time zone information but in fact it does not contain any time zone information. LocalDateTime simply shows the time as given by the Operating system. The Operating System's clock has time zone information. The OS uses machine clock (which is always in UTC) and the time zone information (which is provided by the user while setup) to show the local date time.
Instant, on the other hand, takes its time using the machine clock instead of relying on the operating system.
Callable.call() allows you to declare checked exceptions while Runnable.run() does not. So if your task throws a checked exception, it would be more appropriate to use a Callable.
Notice that, at compile-time, the compiler has full type information available but this information is intentionally dropped in general when the binary code is generated, in a process known as type erasure.
reification=
This is just the opposite of type erasure. Here, all the type information is preserved in the byte code. In Java, arrays are reified. For example,
ArrayList[] alArray = new ArrayList[1];
Collection[] cArray = alArray;
cArray[0] = new HashSet();
The above code will compile fine. But it will throw an java.lang.ArrayStoreException at run time because the byte code contains the information that cArray actually points to an array of ArrayLists and not of HashSets.
In the standard Collection classes, Vector and Hashtable are threadsafe but slower.
Some operations may throw an UnsupportedOperationException. This exception type is unchecked, and code calling these operations is not required to explicitly handle exceptions of this type.
Member variables of the outer instance can be referred to using only the variable name within the inner instance ONLY WHEN that variable is not shadowed by another variable in inner class.
public class TestClass {
static int si = 10; int ii = 20;
public static void inner() {
int ai = 30; //automatic variable
ai = 31; //ai is not effectively final anymore.
final int fai = 40; //automatic final variable
class Inner {
public Inner() { System.out.println(si+" "+fai); }
}
new Inner();
}
public static void main(String[] args) { TestClass.inner(); }
}
Since method inner() is a static method, only si and fai are accessible in class Inner. Note that ai and ii are not accessible. If method inner() were a non - static method, ii would have been accessible. If the line ai = 31; did not exist, ai would have been accessible.
// automatic variable: effectively final? Local variables automatically cease to exist when the execution of the block in which they are declared completes.
public class TestClass{
static int si = 10; int ii = 20;
public void inner(){
int ai = 30; // automatic variable
ai = 31;// ai is not effectively final anymore!! therefore not accessible from Inner constructor !!
final int fai = 40; // automatic final variable
class Inner{
public Inner() { System.out.println(si+" "+ii+" "+fai); }
}
new Inner();
}
public static void main(String[] args){ new TestClass().inner(); }
}
Non-static inner classes can contain final static fields (but not methods).
interface F{
default void m(){ }
abstract void n();
}
The use of abstract keyword is redundant here, but it is legal. Remember, an interface having a default method is not legal but having the abstract method is legal and makes this a legal interface.
public int hashCode()
Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable.
For answering questions in the exam, it is extremely important for you to understand the following description given for the equals method:
It is reflexive: for any reference value x, x.equals(x) should return true.
It is symmetric: for any reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the object is modified.
For any non-null reference value x, x.equals(null) should return false.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any reference values x and y, this method returns true if and only if x and y refer to the same object (x==y has the value true).
Note: that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
Non-static nested classes, unlike normal package classes, can have any type of accessibility.
Methods in non-static inner classes cannot be static: Declaring a nested class static only means that instances of the class are created without having an outer instance. It does not put any limits on whether the members of the class can be static or not.
Local (i.e. inside a method) nested classes cannot be declared static.
A static nested class can contain a non-static inner class.
A nested class is any class whose declaration occurs within the body of another class or interface.
A top level class is a class that is not a nested class.
An inner class is a nested class that is not explicitly or implicitly declared static.
Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes
Further, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.
Inner classes can declare a static members only if it is a constant (i.e. final). To create a class variable for an inner class, the programmer must place the desired variable in an enclosing class. It is helpful at this point to abuse the terminology somewhat, and say, loosely, that the static keyword always marks a "top-level" construct (variable, method or class), which is never subject to an enclosing instance. This shows why an inner class cannot declare a static member, because the entire body of the inner class is in the scope of one or more enclosing instances.
An inner class can extend its outer class
More than one inner instance can be associated with the same outer instance.
Member variables of the outer instance are always accessible to inner instances, regardless of their accessibility modifiers
All name-value maps such as java.util.HashMap and java.util.TreeMap implement java.util.Map and all collections such as java.util.ArrayList, and java.util.LinkedList implement java.util.Collection.
Note that SortedMap is an interface and not a class.
Callable interface is very similar to Runnable interface and is used with the classes of the Executor framework. Runnable isn't used in a framework, but can be consumed by Executor framework.
A Thread .wait can be "woken up" by another thread calling notify on the monitor which is being waited on whereas a sleep cannot.
Sinceanonymous classes can't have constructors, classes can reference variables from containing scopes. For an anonymous class these can be instance variables from the containing class(es) or local variables that are marked final and used as initializer.
class Main {
public static void main(String[] args){
Whatever w = new Whatever();
w.innerA();
}
interface I1 {
public abstract void mA();
public static interface InnerI1 {
public static final int k = 1;
public abstract void innerA();
}
}
}
class Whatever implements Main.I1.InnerI1 { // demonstrates static inner interface
public void innerA() {
System.out.println("Whatever");
}
}
public class A // outer class
{
static public class B //Static Nested class . It can be used in other places: A.B b = new A.B(); There is no outer instance.
{
}
class C //Inner class. It can only be used like this: A.C c = new A().new C(); Outer instance is needed.
{
}
}
The modifier static pertains only to member classes, not to top level or local or anonymous classes. That is, only classes declared as members of top-level classes can be declared static. Package member classes, local classes (i.e. classes declared in methods) and anonymous classes cannot be declared static.
Top Level Class: It's simply any class that's not a nested class. If your file is Foo.java, and your class is Foo, then it's a top level class.
Local classes, classes in local scope of a method, cannot be declared static.
Package member classes, classes declared at the level of the package declaration , cannot be static.
// unpredictable results. sometimes the parallel stream prints 1,2, or 3 values.
// .findFirst() seems to work on each thread independently
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> stringList = Arrays.asList("1","1","2","3","4");
stringList.parallelStream()
.limit(3)
.peek(System.out::println)
.findAny();
System.out.println();
stringList.stream()
.limit(3)
.peek(System.out::println)
.findAny();
}
}
// shows that conversion from DoubleStream to Stream<Double> can be done
import java.util.Random;
import java.util.stream.DoubleStream;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
DoubleStream i = DoubleStream.generate(new Random()::nextDouble);
Stream<Double> o = i.parallel().boxed(); // conversion
o.limit(10).forEach((x) -> {String y = Double.toString(x); System.out.println(y);}) ;
}
}
Without .count() on this stream, it would print nothing:
DoubleStream b = DoubleStream.of(1.1,2.2,3.3,4.4,5.5);
b.limit(2).peek(System.out::println).count();
DoubleUnaryOperator:
DoubleStream b = DoubleStream.of(1.1,2.2,3.3,4.4,5.5);
b.map(n -> n*n).forEach(System.out::println);
DoubleStream.Builder is a Consumer with .accept method:
DoubleStream.Builder b = DoubleStream.builder();
b.accept(1.1);
b.accept(2.2);
b.accept(3.3);
b.accept(4.4);
b.build().forEach(System.out::println);
Given this collector:
.collect(Collectors.groupingBy(Employee::getGender,
Collectors.groupingBy(p -> p.getDob().getMonth(),
Collectors.mapping(Employee::getName, Collectors.joining(", ")))
)
);
// collector will have keys of gender mapping to values containing keys of MONTH containing concacenated Name values
// this is easy to determine by knowing this pattern of how the collector builds elements
CharSequence is an interface that String and StringBuilder use.
Stream<String> s = Stream.of("1","2","3");
Optional<String> o = s.collect(Collectors.minBy(Comparator.reverseOrder())); //Will return the highest number 3, not lowest 1
For .collect(Collectors.groupingByConcurrent(Employee::getGender, Collectors.counting()));
it will result in a Map of gender keys to count of values
.allMatch(x->x.indexOf("o")>0); // this could cause the stream to end immediately if first item doesnt match
Careful: compile error because member variable 's' is not accessible from the inner class (such as a Swing button listener). This is because the inner class is created in a static method (main) so it does not have any reference to TestFrame object.
Be careful of static main method not creating an instance of this class so you can access instance var outside of main.
Know the difference:
java.io.FileNotFoundException
java.nio.file.NoSuchFileException
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
Note that if one path has a root (for example, if a path starts with a // or c:) and the other does not, relativize cannot work and it will throw an IllegalArgumentException.
This wont compile without a no-arg constructor defined:
public enum Coffee{
ESPRESSO("Very Strong"), MOCHA, LATTE;
public String strength;
Coffee(String strength) {
this.strength = strength;
}
}
It's ok to cast an integer Treeset to (Treeset) without its generic identifier. Note: Personally, i dont see how its possible since the compiler needs to make sure the items inside are comparable?
If you use TreeSet.subSet, then the array backed set is bound to its "range" and you cant add items outside that range.
I had a question where the Runnable constructor called .start but the program main method called .run. This meant that successive calls of .run didnt create a separate new thread!!
Never knew this existed:
int r = ThreadLocalRandom.current().nextInt(1, 11);
NoSuchFileException is a subclass of IOException. In the same multi-catch block, you cannot include classes that are related by inheritance.
Watch out for private methods in extended classes.
.peek can be used like .map: they both take Function lambda :
source.stream().peek(item->{destination.add(item); })....
Thread implements Runnable and so it is a Runnable
Path p = Paths.get("c:\\", "whatever/ok");
System.out.println(p); //prints c:\/whatever/ok
Given where both .dat files must be in same folder:
Path p1 = Paths.get("c:\\company\\records\\customers.dat");
This is ok: Path p2 = Paths.get("c:", p1.subpath(0, 2).toString(), "clients.dat");
Don't do this:
Statement stmt = null;
Connection c = DriverManager.getConnection("jdbc:derby://localhost:1527/sample", "app", "app");
try(stmt = c.createStatement();)
{ ...
// Statement object must reside within the try-with-resources block
This is valid:
Properties p = new Properties();
p.setProperty("user", userid);
p.setProperty("password", pwd);
Connection c = DriverManager.getConnection(dburl, p);
This is NOT valid:
Connection c = DriverManager.getConnection(url);
c.connect(userid, pwd)
The actual classes for Connection, Statement, and ResultSet interfaces are provided by the JDBC driver and are therefore driver dependent.
return 0; // ok as a hashcode but very bad practice
Given a ConcurrentHashMap, this might not get an exclusive lock:
if(!cache.containsKey(key)) cache.put(key, value);
But this would:
putIfAbsent(key, value);
// for concurrent class, they are save with getters and setters and putters
For an immutable class, it shouldn't have setters, even if they are private.
Once final vars are set in the class, you wouldn't want to change them with a setter.
You need to provide generic implementation that can be overridden by the subclasses:
WRONG: This doesn't require the class to be abstract. A regular base class can also achieve this.
Given: private ReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
and
lock.readLock().unlock();
As a rule, assertions should not be used to assert the validity of the input parameters of a public method.
a savePoint instance must be passed to .rollback(savepoint) !
Remember that type safety of generic classes is checked only at compilation time. To allow legacy code to run without any modification, the compiler relaxes the rules when you pass a type safe class to a legacy method. However, the compiler warns you that this is a potentially dangerous operation because the legacy code can add any element to your typesafe collection that is not supposed to be added.
Considering:
class Outsider {
public class Insider{ }
}
public class TestClass {
public static void main(String[] args) {
Outsider os = new Outsider();
// 1 insert line here
}
}
// You cannot refer to Insider class directly. You must use Outsider.Insider to declare the type of variable in.
// This is ok: Outsider.Insider in = os.new Insider();
class B {}
class B1 extends B {}
class B2 extends B {}
public class ExtendsTest {
public static void main(String args[])
{
B b = new B();
B1 b1 = new B1();
B2 b2 = new B2();
// insert statement here
}
}
Compiler will check types for casting, but for some, it only catches at runtime, based on not being able to see FULLY into the actual object. Compiler can only see metadata about underlying object (see #2) :
1. b1 = (B1) b; // It will pass at compile time but FAILS at RUNTIME as the actual object referenced by b is not a B1.
2. b2 = (B2) b1; // It will not compile because b1 can never point to an object of class B2.
3. b1 = (B) b1; // This won't compile. Another cast is needed. i.e. b1 = (B1) (B) b1;
4. b2 = b; // It fails at compile time because an object referenced by b may not be a B2, so an explicit cast must be done.
HashSet is a Set not a Map
Must understand why this will never print a 1,2 and will never print 1,1:
public class Counter {
private int count;
public void increment(){
System.out.println(count++);
}
}
Statment has a setMaxRows method that limits the total number of rows returned by the ResultSet.
Remember, when using a interface reference, you can't use methods that are not mentioned in the interface.
These 2 are equivalent, given class must be instance of B BUT not instance of C :
! ( !(o instanceof B) || (o instanceof C)) = ! ( false || false ) = true
(o instanceof B) && (!(o instanceof C)) = true && true = true
// 2 threads: so we cannot determine which one sets x
public class TestClass implements Runnable{
volatile int x;
public void run(){ x = 5; }
public static void main(String[] args){
TestClass tc = new TestClass();
tc.x = 10;
new Thread(tc).start(); // 1
System.out.println(tc.x);
}}
The SavePoint feature of JDBC is tailor made for this purpose. At the end of each step, the process can create a save point. Later on, when the process encounters the special condition, it can roll back the transaction up to any of the previous save point and continue from there, instead of rolling back the whole transaction and losing all the values. For example:
connection.setAutoCommit(false);
stmt.executeUpdate("update student set status=1"); \\1
SavePoint savePoint1 = connection.setSavePoint("step1done");
stmt.executeUpdate("update student set gpa=4.0"); \\2
if(special condition){
connection.rollback(savePoint1);
}
connection.commit(); //query 1 will be committed but query 2 will not be committed.
The auto-closeable variables defined in the try-with-resources statement are implicitly final. Thus, they cannot be reassigned.
Prepared statements are faster:
If we are using PreparedStatement the execution time will be less. First time RDBMS comiple the SQL and PreparedStatement is executed then other calls doesn't compile the SQL only execute the SQL within the connection live.
PreparedStatement has specific methods for additional SQL column type such as setBlob(int parameterIndex, Blob x) and setClob(int parameterIndex, Clob x)
rs.getString is ok for a integer type from a SQL resultSet since int can be converted to a string.
ResultSetMetaData gives you the information about the result of executing a query. You can retrieve this object by calling getMetaData() on ResultSet.
ResultSetMetaData contains several methods that tell you about the ResultSet. Some important methods are:
getColumnCount(), getColumnName(int col), getColumnLabel(int col), and getColumnType(int col). Remember that the column index starts from 1.
The synchronized keyword can be applied only to non-abstract methods that are defined in a class or a block of code appearing in a method or static or instance initialization blocks. It cannot be applied to methods in an interface. Don't use synchronized on an abstract method, such as a interface method.
When deserialized, the value of ti is set to 0:
class Boo implements Serializable {
transient int ti = 10;
static int si = 20;
}
A DB Connection is always in auto-commit mode when it is created.
Path p1 = Paths.get("\\photos\\vacation");
Path p2 = Paths.get("\\yellowstone");
System.out.println(p1.resolve(p2)+" "+p1.relativize(p2)); // prints \yellowstone ..\..\yellowstone
Using .relativize():
Path p1 = Paths.get("x\\y");
Path p2 = Paths.get("z");
Path p3 = p1.relativize(p2);
System.out.println(p3);
Observe what happens when you append this path to p1:
x\y + ..\..\z
=>x + ..\z
=>z
A .java resource bundle is technically the .class file generated from the .java file, not the source .java file itself.
The overriding method can declare any subset of the checked exceptions (or sub classes of those exceptions) declared in the overridden class. "No exception declared at all" is a valid subset that will work.
Note that overloading method can throw just about any exception. It does not have any restrictions.
Connection connection = ...
try(Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("select * from STUDENT"); ) {
while(rs.next()){
// this try block actually wont close the connection if you want to re-use it
// closing Connection would close both the Statement and ResultSet objects
}
}
In concurrent computing, a deadlock is a state in which each member of a group of actions, is waiting for some other member to release a lock
A livelock is similar to a deadlock, except that the states of the processes involved in the livelock constantly change with regard to one another, none progressing. Livelock is a special case of resource starvation; the general definition only states that a specific process is not progressing.
Livelock could occur when a program tries to recover itself from a Deadlock and 2 threads try to recover at the same time; threads still respond to each other during livelock.
ForkJoinTask (Action<Void> returns Future<Void>) = RecursiveAction
.compute method returns void
.compute method creates copies of the task if it needs more workers
.compute method calls .invokeAll on each task in a recursive manner (2 at a time?)
.invokeAll doesn't return anything, and generally we call the 2-arg version of that method, but it also has a varargs variety and Collection variety
ForkJoinTask (Action<T> returns Future<T>) = RecursiveTask
.compute method returns T, which needs to be joined
.compute method forks more work with call to .fork()
.compute method calls new Task(...).compute() + otherTaks.join() (also 2 at a time)
.join is a blocking call and the thread will wait for it (CyclicBarrier .await and Future .get will also block)
DON'T call otherTask.fork().join, since that would be single threaded performance
NOTE: if you didn't use Callable, and wanted to let the caller know the thread work is finished, you could execute a .callback method after calling .join() on a thread.
BufferedReader has a .readLine method, not a Reader!! For example: Console .reader() returns a Reader. SO, don't try c.reader().readLine()
Writer .flush or .close throws IOException when the object is already closed.
File.getParent returns a String, not a File object.
The binary FileInputStream class does NOT have a .mark method. Thats a feature of Reader classes.
LocalDateTime class does not have a .toInstant() method. Only ZonedDateTime has that.
LocalDate pieDate = LocalDate.of(2017, Month.JANUARY, 23);
LocalTime pieTime = LocalTime.of(0,0);
LocalDateTime pieDateTime = LocalDateTime.of(pieDate, pieTime);
DateTimeFormatter f2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.SHORT);
//System.out.println(f2.format(pieTime)); // this line UnsupportedTemporalTypeException
//System.out.println(f2.format(pieDate)); // this line UnsupportedTemporalTypeException
System.out.println(f2.format(pieDateTime)); // this line throws Exception at runtime
System.out.println();
DateTimeFormatter f3 = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM);
System.out.println(f3.format(pieTime));
//System.out.println(f3.format(pieDate)); // this line UnsupportedTemporalTypeException
System.out.println(f3.format(pieDateTime));
There is a DateTimeFormatter class, but not a DateFormatter class.
Duration.ofDays(1) is a actual convenience method. Its just a bunch of seconds. Don't be confused that the method only exists on Period class.
int month = Month.MARCH; // is BADD!!! dont assign enum to int.
Be careful of methods not handling or declaring their checked exceptions! Look for usages of checked exceptions.
class BearException extends RuntimeException
BearException b = new RuntimeException(); // wont compile unless 'new' object is a BearException or its sub-class
Any Exception extending Throwable is technically a 'checked' exception.
MissingResourceException is un-checked. It does not extend IOException, as you might think.
IllegalStateException is un-checked.
Remember that the scope of try-with-resources variables ends when the try statement is complete !!!!! Don't try to use the variable in a catch nor in a final clause.
The order of exceptions in a multi-catch does not matter, only that they not be subclasses of one another. But, for exceptions that extend the other, its true that the narrower exceptions must be above the broader ones.
try{ // this is ok, because SQLDataException is more specific
} catch(java.sql.SQLDataException | IllegalStateException e){
} catch(java.sql.SQLException e){
}
Be careful of new Exception() without a throw because it won't really throw it.
Don't use a variable twice in the same method. For example: If main method has an arg called a, then don't us a for another variable in the method.
Exception class takes Throwable as args to its constructor. This is obvious but I am calling it out.
Both anyMatch() and allMatch() take a Predicate as a parameter.
There is no built-in method to map a value to a boolean primitive. No such thing as .mapToBoolean
stream.sorted().findFirst() returns an optional, not a specific value
// from http://www.java2s.com/Tutorials/Java/java.util.stream/LongStream/
// conversion from long to int requires a cast!!
import java.util.stream.LongStream;
public class Main {
public static void main(String[] args) {
LongStream b = LongStream.of(1L, 2L, Long.MAX_VALUE, Long.MIN_VALUE);
b.mapToInt(n -> {return (int)n;}).forEach(System.out::println);
}
}
Stream sorted() requires all the elements be available to sort, it never completes if the .filter before it has no limit.
A Stream of IntStream objects probably needs .flatMapToInt to convert down to a single stream of Integers.
import java.util.Arrays;
import java.util.List;
import java.util.stream.DoubleStream;
class Main {
public static void main(String[] args) {
List<String> stringList = Arrays.asList("1.2","2.2","3","4","5");
stringList.stream()
.flatMapToDouble(n-> DoubleStream.of(Double.parseDouble(n)) )
.forEach(System.out::println);
}
}
Optional has a .filter , .map, and .isPresent method. So, you could have optional.filter(...).map(...).isPresent()
It makes sense you might have an Optional that needs to be filtered down to finally determine if something is present.
Both Collection and String have an isEmpty() method
Stream has a min() method. However, since we are working with a Stream, this method requires a Comparator as a parameter and so don't fall for it having 0 params.
Given: stream.sorted(Comparator::reverseOrder)
The sorted() method allows an optional Comparator to be passed as a reference. However, Comparator.reverseOrder() does not implement the Comparator interface. It takes zero parameters instead of the required two. Since it cannot be used as a method reference.
Comparator<Song> songRatingComparator = Comparator.comparing(Song::getRating);
Collections.sort(songList, songRatingComparator.reversed());
OR
List<Song> sortedSongList = songList.stream()
.sorted(Comparator.comparing(Song::getRating).reversed())
.collect(Collectors.toList());
Optional has a map method: If a value is present, apply the provided mapping function to it
The Optional class has an isPresent() method that doesn’t take any parameters. It returns a boolean and is commonly used in if statements. There is also an ifPresent() method that takes a Consumer parameter and runs it only if the Optional is non-empty.
The sorted() method takes an optional Comparator as the parameter
findAny() returns an Optional and ifPresent() is declared on Optional and takes a consumer.
This custom collector is ok: Collectors.toCollection(ArrayList::new)
.anyMatch returns a boolean, not an optional!
Stream has a .mapToInt method , but not IntStream. IntStream does have a .mapToLong, .mapToObj, and .mapToDouble method.
IntFunction<R> takes a primitive argument as input and a generic argument for the return type.
Although Java does not include built-in support for primitive functional interfaces that include float, char, or short, there is nothing to prevent a developer from creating them in their own project
IntFunction<Integer> takes an int value and returns an Integer.
A local variable that is neither final nor effectively final cannot be used inside of a lambda expression.
Although the Double class does have a longValue() method, the left-hand side of the lambda expression must use the primitive double, not the wrapper Double.
(double d) -> d.longValue()
A DoubleToIntFunction probably would need to cast the double to Integer to return a int.
BinaryOperator<Integer> takes 2 integers and returns an integer.
ObjDoubleConsumer takes 2 args while DoubleConsumer takes 1 only!!!!
If your using a Supplier lambda, make sure it returns a value!
Be careful using Consumer without its generic argument: Consumer<String> its ok without the generic parameter only if you dont try to call a unavailable method on Consumer<Object>
The IntUnaryOperator functional interface is not generic, so the argument IntUnaryOperator<Integer> is bad.
Lambdas for Supplier<Double> can return a null value since Double is an object type, while lambdas for DoubleSupplier cannot; they can only return primitive double values.
Method references can get passed either the instance or a parameter but not both. So, is not possible to use String::charAt as a method reference since you would need both
Don't do Wash<List> wash = new Wash<ArrayList>(); // BAD!! a generic type cannot be assigned to another direct type unless you are using upper or lower bounds in that statement.
Stream .filter requires a Boolean lambda or functional ref!
Wash wash = new Wash<String>(); will compile but shows a warning about the reference type.
Re-using a finalized stream is not caught until Runtime with a IllegalStateException
When adding Comparable objects to a TreeSet, the TreeSet doesn't check that it implements Comparable until runtime.
Given:
class Robot {public String playSay = "Play";}
Robot prime = new Robot() {
public void play(System.out.println(this.playSay));
}
This code, because its an anonymous class, is able to access this.playSay from the parent class (or interface) it implements/extends.
Be careful of protected abstract methods meant to be extended. You can't extend them as package-private or private.
While having a static method is allowed in a extended interface, marking a static method with the @Override annotation is not because only member methods may be overridden.
Member inner classes, such as a private inner class, cannot include static methods or variables!
A declaration of anyonymous innner class (from interface) needs a "new InterfaceName" declaration and also MUST end with a semi-colon!
enum constructors must be private, meaning a protected constructor does not compile. A package-private constructor is "assumed" to be private, and therefore effectively private, BTW
.invokeAll(null) will compile but throws null pointer at runtime
ScheduledExecutorService .scheduleAtFixedRate requires 4 args:
Runnable, long initialDelay, long period, TimeUnit
.scheduleAtFixedRate takes a Runnable, not Callable
Both of these are ok but the scopy of their synchronization is different:
public static synchronized void method1 // synchronizes on ClassName.class object
public synchronized void method2 // synchronizes on this. object
List<Integer> db = Collections.getSynchronizedList(new ArrayList<>()); // is thread-safe on .get and .set, such as within a Stream .map operation, BUT NOT around interators created from it.
This proves it:
List<Integer> l = new ArrayList<>();
IntStream.generate(() -> ThreadLocalRandom.current().nextInt(10))
.limit(5)
.map(a -> {l.add(a); return a;})
.forEach(f -> System.out.println("" + f));
System.out.println(l); // prints same numbers in same order as lambda expression
IntStream.iterate(1, i -> i+1).limit(5).forEach(System.out::println); // prints 1-5, not 2-6! identity is always included
IntStream.iterate(1, i -> 8).limit(5).forEach(System.out::println); // prints 1 8 8 8 8
When using ForkJoinPool framework, make sure you call .fork and .join at some point, otherwise your mis-using it.
RecursiveTask .compute method is protected!!! Remember, RecursivTask is not an interface, its an abstract class, and in that context this makes sense.
The precise requirements for Java to perform a concurrent reduction using the collect() method, which takes a Collector argument are: Collector argument must be concurrent, the stream OR collector is unordered, and the stream is parallel . Recall from your studies that a Collector is considered concurrent and unordered if it has the Collector.Characteristics enum values CONCURRENT and UNORDERED, respectively. Elements of a stream are not required to implement Comparable in order to perform a parallel reduction.
UNORDERED essentially means that the collector is both associative (required by the spec) and commutative (not required).
The Enum Collector.Characteristics, basic has those 2 characteristics.
Also, a stream which is already unordered, is not affected by the UNORDERED characteristic of a Collector
Collector must be concurrent probably to support usage of a parallel stream?
Be cafeful of iterating a List/Deque with a for loop, and performing .add or .push, since non-concurrent, non-synchronized, lists will throw ConcurrentModificationException at runtime since neither allows modification while they are being iterated upon!!
List<Integer> l = new ArrayList<>(Arrays.asList(1,2,3,4,5));
for (Integer x : l) l.add(9);
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
On BlockingDeque, the blocking methods .offerLast() and .pollFirst() each throw a checked InterruptedException and must be handled
Deadlock describes a situation where two or more threads are blocked forever, waiting for each other.
Hard to believe but, Executors.newCachedThreadPool and .shutdown do not need to be wrapped to catch a checked exception but they do sometimes throw a runtime exception.
You can write a java.util.concurrent class without catching exceptions. On the other hand, use of Callable can throw any checked exception.
.forEach(() -> service.submit(() -> waitToBeFinished)); // lambda in lambda is ok
Instead of implementing a anonymous Runnable, you could do this instead, but if the tasks dont finish, the JVM might not shutdown:
Executors.newSingleThreadExecutor().submit(Callable/Runnable);
A synchronous request blocks the client until operation completes. An asynchronous request doesn’t block the client.
This is confusing, and anti-intuitive, because of dictionary definition:
synchronous 1669, "existing or happening at the same time"
FutureTask is a turnkey implementation of "A cancellable asynchronous computation."
Calling .get on a Future<Object> doesn't necessarily need a cast:
System.out.println("Print it: "+ fo.get()); // where object is a Double
see: https://repl.it/KUj3/8
The three-argument reduce() method returns a generic type, while the one-argument reduce() method returns an Optional.
The BaseStream interface, which all streams inherit, includes a parallel() method. Of course, the results of an operation may change in the presence of a parallel stream, such as when a stateful lambda expression is used, but they all can be made parallel.
its possible that a JVM may only allocate a single thread to a parallel stream
certain stream operations, such as limit() or skip(), force a parallel stream to behave it a serial manner
ForkJoinPool has a .invoke method and a .shutdown method
RecursiveAction and RecursiveTask requires implementing .compute and you start them with .exec
Be careful of forked tasks modifying a non-static, possibly non-shared variable
If a recursive task splits off the work in 2 chunks (from itself in a main method), you end up with 3 objects: the original, the first from .invoke, and the recusive 2nd task via .invokeAll
A race condition is an undesirable result when two tasks that should be completed sequentially are completed at the same time. The result is often corruption of data in some way.
If you fork off a number of threads using .execute, then they might not all be finished unless you use ExecutorService.awaitTermination()
.scheduleWithFixedDelay or .scheduleAtFixedRate NOT .scheduleAtFixedDelay!!
ConcurrentSkipListMap implements the SortedMap interface, in which the keys are kept sorted
A .reduce accumulator (not combiner) must be both stateless and associative even if it ignores the 2 input parameters.
List has a .stream method and .parallelStream BUT NOT .parallel . Use .parallel only from a Stream object.
.findAny on a parallel + ordered stream is still unpredictable.
A LinkedBlockingDeque includes blocking methods in which elements can be added to the beginning or end of the queue, while waiting at most a specified amount of time.
BlockingDeque is an interface, not a class.
Future.get() throws a checked InterruptedException and ExecutionException, both of which must be handled or declared by the calling method.
Resource starvation is when a single active thread is perpetually unable to gain access to a shared resource. Livelock is a special case of resource starvation, in which two or more active threads are unable to gain access to shared resources, repeating the process over and over again.
the Concurrent classes order read/write access such that access to the class is consistent across all threads and processes, while the synchronized classes do not.
The .submit method returns a Future and is from ExecutorService and will take a Runnable or Callable.
Be aware of the difference between Executors class and ExecutorService .
Executors methods provide ExecutorService objects.
Thread has a .run method that you override, and the .start method triggers it.
You can .count a Stream<String>:
try (Stream<String> lines = Files.lines(path, Charset.defaultCharset())) {
long numOfLines = lines.count();
...
}
Files.exists() and Files.isDirectory wont throw a checked exception.
There is a version of Files.copy() that takes an InputStream, followed by a Path and a list of copy options. So, don't try to pass a Reader.
Files.readAllLines() throw a checked IOException, which must be handled or declared!!!
./stars/../solar/
.subPath(0,2) reduces it to first 2 elements: ./stars
.normalize(Paths.get("./stars") results in stars
the Files.getFileAttributeView() method requires a reference to a subclass of FileAttributeView, such as BasicFileAttributeView.class.
BasicFileAttributeView does not contain a creationTime() method but BasicFileAttributes does.
Be careful of Path.get where Paths.get is what you intended!
Path.getNameCount because Path has no .size method
A Path like this is ok: "/what/ever/path.." . Folders can have periods in the name.
be aware of if statments not in brackets!
getRoot() on a relative path returns null!
toRealPath() interacts with the file system and therefore throws a checked IOExceptio
So, be careful of lambdas that interact with the file system.
try {
Path real_path = path.toRealPath(LinkOption.NOFOLLOW_LINKS);
System.out.println("Path to real path: " + real_path);
} catch (IOException e) {
System.err.println(e);
}
The BasicFileAttributeView class contains methods to read and write file data, while the BasicFileAttributes class only contains methods to read file data. The advantage of using a BasicFileAttributeView is to also modify file data
The BasicFileAttributesView class has a .readAtttributes method that returns a BasicFileAttributes object. Also, BasicFileAttributeView has a .setTimes method whereas the BasicFileAttributes class has read only accessors for time.
Files.list() returns a Stream<Path>, not a List<Path>
If p2 is an absolute path, this means that p1.resolve(p2) just returns p2.
The Files.delete() method has a return type of void, not boolean
Files.deleteIfExists will check before delete and so it returns boolean
Neither File nor Path have a method for deleting an entire directory tree.
When copying file with BufferedReader, make sure line needs are retained!
The Path method getFileName() returns a Path instance, not a String!! whaaat? .getPathOfFile() would have been a better name.
The AtomicMoveNotSupportedException is only possible when the ATOMIC_MOVE option is passed to the move() method. Passing REPLACE_EXISTING wont cause it. Maybe DirectoryNotEmptyException
Path p = new Path("/bag/of/tricks/.././disappear.txt");
Path p2 = path.subpath(2,3); //returns tricks
p2.getName(1); // IllegalArgumentException
Files.size(Path) returns a long, indicating size of a file.
Files.walk returns a Stream<Path> which needs a terminal action.
Files.isSameFile(file1,file2); // false if both are not absolute or both are not relative
// first checks if the Path values are equivalent in terms of equals(): One is absolute and the other is relative, so this test will fail. The isSameFile() method then moves on to verify that the two Path values reference the same file system object.
Files.isHidden(Path arg); // ok
File.isHidden(Path arg); // BAD, does not exist, should be File.isHidden()
Static variables do not become part of a serialized object, from ObjectOutpuStream: only instance members that aren not transient.
new BufferedInputStream(new FileReader ... // BAD
Writer pie = new FileWriter("afile.txt");
pie.flush(); // creates a file
new File("fudge.txt").mkdirs(); // creates a folder called fudge.txt
InputStream.read(new byte[2]) will read 2 bytes into the buffer
// reminder of how to copy a file with IS and OS:
private static void copyFileUsingStream(File source, File dest) throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length); // on last iteration, only writes the length of buffer
}
} finally {
is.close();
os.close();
}
}
Given:
Console c = System.console();
c.reader().read(); // c.reader() returns a Reader object, which has a .read method NOT a .readLine method!
// InputStream is parent class of StringReader and InputStreamReader and it has the .read method on it
File.toURL : This method does not automatically escape characters that are illegal in URLs. It is recommended that new code convert an abstract pathname into a URL by first converting it into a URI, via the toURI method, and then converting the URI into a URL via the URI.toURL method.
Note that the valid way to iterate over all elements of a file using ObjectInputStream is to continue to call readObject() until an EOFException is thrown. Swallowing that EOFException is probably ok since the exception will still stop the loop.
FileWriter and BufferedWriter can be used in conjunction to write large amounts of text data to a file in an efficient manner. For binary data, you might use FileOutputStream and BufferedOutputStream.
Java Console does not have a .print method. It has a .format and .printf method.
When looking for compiler errors: remember to also look for final variables being modified and methods missing throws clauses.
A try-with-resources can have a catch and also a finally in it in the same try statement. It's ok.
System.getProperty("path.separator") is used to separate sets of paths, not names within a single path. Example: in classpath
ObjectInputStream.readObject requires the object be Serializable
Don't call Console c = new Console(); !! Use System.getConsole()
Be suspicious of any code samples that call the mark() or reset() method without first calling markSupported().
InputStream.mark(readLimit): The readlimit arguments tells this input stream to allow that many bytes to be read before the mark position gets invalidated.
FileOutputStream and FileReader are both low-level streams that operate directly on files
ObjectInputStream is a high-level stream that can only wrap an existing InputStream.
Won't Compile: new BufferedWriter(new FileOutputStream(new File("whatever.txt"))); //BAD
Will compile: new BufferedWriter(new FileWriter(new File("whatever.txt"))); // Good
java.io.File.getLength() and .createDirectory methods DO NOT EXIST. It's File.length() and File.mkdir() .
Writer, InputStream, OutputStream, and Reader are abstract classes, not interfaces!
Even though a resource file could be called Colors_ZH.properties, it wouldn't work because the file name needs to be lower case. This is a fact even though you could use upper case in the call to .getBundle (and java would adjust for that)
Don't ever call "new ResourceBundle" because it has a private constructor.
Java does not allow looking in a properties file resource bundle once it has matched a Java class resource bundle.
Be careful defining ResourceBundle.getBundle without the fully qualified package name.
Using 1-arg constructor of .getBundle, Since no locale is specified, the code tries to find a bundle matching the default locale and probably wouldn't find a resource like ResName_en.java
resourceBundle.getString("x") might throw missing resource exception, even if you set a default locale that matches a file. If the resource bundle has a "fr" country locale, it will not find a resource bundle named Cars_en.properties, although it would find Cars.properties
There is no get() method on Locale. You need to use a constructor or a predefined Locale constant to obtain a Locale object.
ListResourceBundle and Properties object keys are always Strings
Remember, String v = prop.get("key") wont work without a cast from Object OR use .getProperty instead.
An Instant represents a specific moment in time using GMT. Since LocalDateTime does not have a time zone, it cannot be converted to a specific moment in time.
DateTimeFormatter.ofLocalizedTime will format a LocalDateTime, LocalTime, or ZonedDateTime object but wont work on a LocalDate object because it contains no time component.
Be careful of questions about compiler errors when you would get a runtime exception.
// these are similar
ChronoUnit.DAYS.between(date1, date2)
date1.until(date2, ChronoUnit.DAYS)
BE CAREFUL of LocalDate .plusDays not assigning back to variable, or it will do nothing.
BE CAREFUL of time math subtracting time zone factor! Its 1-12, not 1-10 !
DateTimeFormatter.ofPattern("Whatever: yyyy dd MMM"); // WONT work. Error at runtime.
There is no .plusMonths() method on LocalTime !!!
There is no such thing as the class: DateFormatter! Its DateTimeFormatter!
Runtime exception is thrown, not compile time, on this: LocalDate.of(2017, Month.FEBRUARY, 31)
LocalTime time = LocalTime.of(1,2,3,4);
System.out.println(time); // prints 01:02:03.000000004 // 9 digits of precision because its 1,000,000th of a second.
milli - micros - nano
This can be very subtle, e.g. Stream.iterate(T,UnaryOperator) creates an ordered stream while Stream.generate(Supplier) creates an unordered stream.
forEach does not maintain the ordering. You have to use forEachOrdered if you want to process the stream’s elements in a guaranteed order.
If you avoid .forEach and use .map and then use Collectors.toList(), you'll probably retain order: i need to explore this.
There are cases where Objects::notNull is preferred over Optional::isNullable
The older date-time classes are in java.util , the newer ones in java.time
A Period is measured in days, weeks, months, or years. Duration can measure seconds.
int month = Month.MARCH; // wont compile! an enum cant be assigned to an int!
aDate.minus(aDuration) // throws temporal exception at runtime, watch out
NOTE: DateTimeFormatter .ofLocalizedDate(FormatStyle.SHORT) is able to format a DateTime object containing time+date and wont throw temporal exception in that scenario even though we didnt set a formatter style on time. This is not intuitive because we know there is a .ofLocalizedDateTime method, and we didn't use that.
Watch out with: for(... ){z.plusHours(...);} since it never assigns back to original variable and never really changes time
Supplier<Double> and DoubleSupplier are both functional interfaces.
DoubleSupplier.getAsDouble returns a primitive
Supplier<Double> returns a Double , which could be a null.
OptionalDouble.getAsDouble also returns a primitive and is really only initialized like: OptionalDouble.of(...)
In a method having a try block using an AutoCloseable, if the try block lacks a catch(Exception...) clause, then the method still needs to declare 'throws Exception' !
The Closeable interface defines a close() method that throws IOException only (not SQLException for example).
The AutoCloseable interface defines a close() method that throws Exception.
Remember, printed exception in finally block will replace a printed exception handled from a catch clause.
NotSerializableException is a sub-class of IOException. java.util.MissingResourceException is a runtime exception.
The optional second parameter of an assert statement, when used, must return a value. Using "System.out.println("Whatever") wont work because it returns void. using MyClass.usableVar++ returns a val, so it works.
In a try-with-resources, the resource in the parenthesis must implement Closeable/AutoCloseable AND the resource created there is not in scope for the finally block NOR the catch block since resources are auto closed before that point.
Any catch or finally blocks used with a try-with-resources statement are executed after the declared resources have been closed, not before.
the semicolon (;) after the second resource declaration is optional.
multi-catch blocks cannot contain two exceptions in which one is a subclass of the other.
Where BearException extends RuntimeException, in catching be, it cannot be re-assigned an instance of the superclass RuntimeException without an explicit cast!!!!
An exception defined as 'MyEx extends Throwable', which does not inherit RuntimeException or Error, thus making it a checked exception!
Be careful of this because the try effectively does nothing, since it re-throws, and it would still need to be caught by a throws declaration in the surrounding method. I was tricked by this twice! :
try {
// stuff here that throws a checked exception of any kind
} catch (Exception e) {
throw e;
}
Be careful of syntax errors on test or re-used variables, etc. Brackets instead of parenthesis! Compile errors! Careful of "new Exception("whatever")" without the throw keyword!
With Closeable, after being run once, future calls to close() should not change any data.
Error is an unchecked exception! It is recommended that Error not be caught by most application processes.
IntSummaryStatistics has a .getCount method that returns a long, not int !!
The flatMap() method works with streams rather than collections.
Defining a Function to be passed to .flatMap
https://repl.it/JyQq/10
Be careful of a question defining: Deque<String> queue = ... In that case queue.push() is ok because its a stack.
.allMatch and .anyMatch BOTH take a predicate arg. dont be fooled to use .anyMatch() !!
Stream method .findFirst() returns an optional and so if you want the value you need to call .get or .orElse to get the value.
The mapToLong() method is not available on LongStream so it does not compile. It is available on DoubleStream, IntStream, and Stream implementations.
LongStream .mapToInt() might not compile. You would need to cast it like this:
b.mapToInt(n -> {return (int)n;}).forEach(System.out::println);
A call to .sorted on a stream will enter infinite loop unless all elements are done being generated through the filter. Be careful!
IntStream ints = IntStream.empty();
IntStream moreInts = IntStream.of(3, 6, 9);
Stream.of(ints, moreInts).flatMapToInt(x -> x).forEach(System.out::println);
NOTE: don't use .flatMap(...) here!!!
Optional like Optional<Collection> or Optional<String> contains some of the same methods as Stream , like .filter and .map but not most of the Stream methods like .flatMap, .peek, .sorted, etc. So, this is ok: optionalWhat.filter(...).map(...).isPresent(...);
Stream<Integer> stream = Stream.of(1,2,3);
System.out.println(stream.findAny()); // prints either 1,2, or 3, even when its not parallel
System.out.println(stream.first()); // no such method
System.out.println(stream.min()); // no such method! ; .min(Comparator)
.sorted(Comparator::reverseOrder) :
The sorted() method allows an optional Comparator to be passed as a reference. However, Comparator.reverseOrder() does not implement the Comparator interface. It takes zero parameters instead of the required two. Since it cannot be used as a method reference, the code does not compile. https://repl.it/JyNw/9
Using .flatMap typically has something like x -> x.stream()
for example: List<String> collect = list.stream()
.map(x -> x.getBook()) //Stream<Set<String>>
.flatMap(x -> x.stream()) //Stream<String>
.distinct()
.collect(Collectors.toList());
But can also be done like:
List<String> collect = list.stream()
.flatMap(b -> b.getBook())
.stream().distinct() //Stream<String>
.collect(Collectors.toList());
The Optional class has an isPresent() method that doesn’t take any parameters. It returns a boolean and is commonly used in if statements. There is also an ifPresent(Consumer c) method that takes a Consumer parameter and runs it only if the Optional is non-empty.
The sorted() method takes an optional Comparator as the parameter, which takes two String parameters and returns an int.
this is ok: stream().sorted( (s,t) -> s.length() - t.length() )
When using stream().sorted().findAny(), even though its not using .parallel(), it is highly likely that the sorted first element of the stream will return but it is not guaranteed.
Optional.of(null) throws a NullPointerException if you try to pass a null reference
Its not possible to swap keys of a Map using stream().map((k,v) -> (v,k))
Do it like this:
Map<String, Integer> map = new HashMap<>();
Map<Integer, String> swapped = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
Turn a list into a Map:
Map<String, Object> map = list.stream().collect(Collectors.toMap(Function.identity(), s->s);
LongSummaryStatistics has a .getAverage() method (returns primitive double) but LongStream() has a .average() method returning OptionalDouble !! Think about it: averaging numbers gives a decimal.
LongSummaryStatistics has an .accept(long) method that allows you to add new long values to the statistics.
For Optional<Double> , there isnt a getAsDouble() method and so you use .get ; returns the type of the generic
private static Optional<Double> convert(OptionalDouble od)
{
return od.isPresent() ?
Optional.of(od.getAsDouble()) : Optional.empty();
}
http://www.concretepage.com/java/jdk-8/java-8-stream-allmatch-anymatch-nonematch-example
anyMatch() returns a boolean and takes a Predicate arg
findAny() does return an Optional, but it doesn’t take any parameters
IntStream s = IntStream.empty();
System.out.println(s.average().getAsDouble() ); // exception at runtime unless you use optional.isPresent()
If your using stream.map(s -> s.length()).forEach... its ok if input has to auto-box into Integer
In DoubleStream (DoubleStream<Integer> doesn't exist! think about it!): in this case, the average() method returns an OptionalDouble object.
This compiles:
BooleanSupplier stock = () -> quantity>0;
stock.getAsBoolean(); // not stock.get() !!! ( i know this is confusing: object already knows it is a boolean)
IntSupplier stock = () -> quantity>0;
stock.getAsInt();
Optional<Double> oD = Optional.of(2.1);
Double d = (Double)oD.get(); // this one uses .get . remember: only Optional object has .get() method returning T, needing to be cast.
DoubleBinaryOperator interface has a method operator with "apply" method .applyAsDouble(double left, double right)
IntFunction<T> with return type T
IntFunction<Integer> takes an int value and returns an Integer
this function takes a primitive as arg
it is not possible to define a functional interface that returns two data types
Although Java does not include built-in support for primitive functional interfaces that include float, char, or short, there is nothing to prevent a developer from creating them in their own project
a functional interface that takes no values and returns void is possible. In fact, Runnable is one such example. ( void run() )
IntFunction<R> takes a primitive argument as input and a generic argument for the return type.
Some of the primitive functional interfaces DO include generic arguments. For example: ToIntFunction<A> returns a primitive int but takes a generic object.
http://karols.github.io/blog/2015/08/08/java-8-functional-interfaces-cheatsheet/
import java.util.function.DoubleToLongFunction;
import java.util.*;
public class HelloWorld
{
public static void main(String[] args)
{
System.out.println(Long.MAX_VALUE ); //9223372036854775807
DoubleToLongFunction dl1 = (x) -> {return Long.MAX_VALUE - (long)x;};
System.out.println(dl1.applyAsLong(3.14)); //9223372036854775804
DoubleToLongFunction dl2 = (double s) -> (long)(s * 100); // must cast to long!! cast to Long would not compile!
System.out.println(dl2.applyAsLong(3.14)); //314
}
}
When you define a Functional interface, end it with a semi-colon!!
Function<String,String> f = (s) -> {System.out::println; return "-- " + s;};
DoubleToIntFunction x = p -> p*100 returns a double, and so this wont compile.
Autobox from int to Integer occurs here when: BiFunction<Integer,Double,Integer> w = (s,e) -> s.intValue() + e.intValue()
// yes Integer.intValue() returns a primitive; it would probably also work with autoboxed primitive arg
() -> {return 1/0;} is a valid IntSupplier at compile time because exception is not thrown until runtime.
Deferred execution means the lambda expression is not evaluated until runtime, but it is compiled.
I've seen some questions that have a compile problem answer but they include the answer that would happen if the compile error were not there, tricking you into thinking it might compile.
IntFunction<T> takes an int and returns a Generic value T //will it compile without the T? yes, but...
IntFunction j = (x)->Integer.toString(x);
System.out.println(j.apply(3).length()); // exception at runtime about the generic type missing
ObjDoubleConsumer takes two values, a generic value and a double,and returns void !!!
LongSupplier does not take any values and returns a long value.
Be careful of difference between Function<Double,Integer> , taking 1 arg, vs. BiFunction<Double, Integer, Integer>, taking 2 args (primitive or Number)
IntUnaryOperator , NOT UnaryIntOperator !Don't be tricked!
Java does not have built-in support for primitive functional interfaces that include char, float, or short.
The input type of a UnaryFunction must be compatible with the return type. By compatible, we mean identical or able to be implicitly cast.
import java.util.function.*;
class Main {
public Long wakeUp1(Supplier<Integer> supplier) {
return supplier.get().longValue();
}
public Long wakeUp2(Supplier supplier) {
//return supplier.get().longValue(); // due to missing Generic: error: cannot find symbol! at runtime?
return new Long(0);
}
public static void main(String[] args)
{
Main main = new Main();
main.wakeUp1( () -> {System.out.println("Supplying object 4..."); return new Integer(4);} );
//main.wakeUp2( () -> {System.out.println("Supplying object 4..."); return new Integer(4);} );
}
}
Remember: BiPredicate returns a primitive boolean, not Boolean!
This method wont compile because IntUnaryOperator is not a generic!! UnaryOperator<E> is generic but not primitive type specialization of Unary Operator!
public int takeTicket(int currentCount, IntUnaryOperator<Integer> counter)
...
NOTE: The opposite is also true, if you specify a parameter "Consumer" without its required generic, it compiles on its own but subsequent code that invokes it fails at compile time!
NOTE: This method is ok without Generic: void wakeUp(Supplier supp) - The Supplier functional interface normally takes a generic argument, although generic types are not strictly required by compiler since they are removed by the compiler. It shows a compiler warning only. Example: when supp.get(); is never used, such as not returned by method
NOTE: Not to be confused with something like DoubleFunction<Double>, which looks like it might not be a generic, but it is: takes a double arg and returns a Double.
import java.util.function.ToDoubleBiFunction;
class Main {
public final int number = 6; //will fail compile if you move this var into the main method, making it a local var instead of a instance var because local vars are final and shouldnt be modified
Main() { System.out.println(); }
public final static void main(String... args) {
ToDoubleBiFunction<Integer,Double> tdbf1 = (Integer a, Double b) -> {int c; return b;};
System.out.println(tdbf1.applyAsDouble(Integer.MAX_VALUE, Double.MAX_VALUE));
ToDoubleBiFunction<Integer,Double> tdbf2 = (Integer a, Double b) -> {int c=3; c++; return b;};
System.out.println(tdbf2.applyAsDouble(Integer.MAX_VALUE, Double.MAX_VALUE));
Main main = new Main();
// next example fails to compile: error: cannot assign a value to final variable number
//ToDoubleBiFunction<Integer,Double> tdbf3 = (Integer a, Double b) -> {main.number++; return b;};
//System.out.println(tdbf3.applyAsDouble(Integer.MAX_VALUE, Double.MAX_VALUE));
// why? if you don't try to change the number, its ok
ToDoubleBiFunction<Integer,Double> tdbf4 = (Integer a, Double b) -> {System.out.println(main.number); return b;};
System.out.println(tdbf4.applyAsDouble(Integer.MAX_VALUE, Double.MAX_VALUE));
}
}
A lambda like this is ok and will compile since the effectively final variable c is never used or re-assigned:
(Integer a, Double b) -> {int c; return b;}
BiFunction<Integer,Double,Double> where (s,p) -> s+p
- The sum s+p is of type double, and double can be auto-boxed to Double
Another example:
BiFunction<Integer, Integer, String> biFunction = (num1, num2) -> "Result:" +(num1 + num2);
System.out.println(biFunction.apply(20,25)); //return is converted to String just like a auto-box sorta
DoubleSupplier and Supplier<Double> are both functional interfaces in java.util.function: The major difference between the two is that Supplier<Double> returns the generic type Double, while the other does not return any generic type and instead returns a primitive double. Primitive!
"PECS" is from the collection's point of view. If you are only pulling items from a generic collection, it is a producer and you should use extends; if you are only stuffing items in, it is a consumer and you should use super. If you do both with the same collection, you shouldn't use either extends or super.
The principles behind this in Computer Science is named after
Covariance - ? extends MyClass,
Contravariance - ? super MyClass
Invariance/non-Variance - MyClass
Why doesn't String::charAt work as a method ref?
With method references, only one item can be supplied at runtime. For String::charAt, we need either a String instance with no parameters in the method or a static method with a single parameter. When the charAt() method is an instance method with a single parameter it does not meet this requirement.
Remember: this is because all interface methods are static and public by implication.
Remember: this is why System.out::println works; because its a instance method of PrintStream (even though the PrintStream out object is itself a static object , the instance method println isn't static, but takes 1 arg)
Example:
private static void printNames(List list, Consumer c ){
list.forEach(x -> c.accept(x));
}
ReferenceToInstanceMethodOAPO.printNames(names,System.out::println);
import java.util.*;
class Main {
public static void main(String[] args) {
Wash<List> wash1 = new Wash<List>(); // good
//Wash<List> wash2 = new Wash<ArrayList>(); //bad; ArrayList doesnt extend Collection
//Wash<List> wash = new Wash<? super ArrayList>(); //required: class or interface without bounds
}
}
class Wash<T extends Collection> {}
Printable<LinkedList<String>> list = new Printable<LinkedList<String>>(); // ok
Beware of stream().filter without a Boolean predicate arg. filter(Predicate<? super T> predicate)
First, numbers sort before letters. Second, uppercase sorts before lowercase.
If you have a generic class, the compiler will allow you to instantiate it without generic parameters and/or with generic parameter on the right-hand side of the = symbol! The class reference will assume you meant Object.class . Using such a reference with String would be ok since String uses Object.toString() method: inherited.
Trying to re-use a stream throws an error at runtime, not compile time.
Override .compareTo(O arg) in Comparable, not compare(O arg, O arg2). .compare belongs to Comparator
TreeSet doesn’t look to see if the object can be compared until runtime
REMINDER: Be careful of variable scope.
Marking a static method with the @Override annotation is not allowed because only member methods may be overridden
Member inner classes cannot include static methods or variables. Be careful!
An overridden method may not throw a broader checked exception than it inherits, not even Exception.class !!
NOTE: You may recall that in certain use-cases of exception handling, catching the broadest exception "Exception" class is allowed, which makes the previous statement confusing:
public long getSomeData() throws IOException {
try {
return whatever(...);
} catch (Exception e) { //catch a broader exception; compiler allows this; probably so to handle runtime exceptions also
throw new IOException(e.getMessage(), e);
}
}
anonymous inner class may implement at most one interface, since it does not have a class definition to implement any others
Declaration of anonymous class MUST end with semi-colon. Also, when implementing method Override in anonymous class, make sure you don't declare as package-private, restricting the access modifier narrower than public, or compiler will complain.
A static nested class MUST be instantiated in a static manner!!!! not using new!!!
An enum cannot be marked abstract, nor can any of its values, but its methods can be marked abstract
enums cannot extend other enums
enum constructors must be private, or it wont compile.
NOTE! if enum constructor is missing a modifier, thats ok since it is assumed to be private
You are allowed to mark these as final or abstract:
1. static nested class
2. local inner class
3. member inner class
Neat example of a final var that is modifiable through Reflection:
import java.lang.reflect.Field;
public class FinalTransient {
private final transient Object a = null;
public static void main(String... args) throws Exception {
FinalTransient b = new FinalTransient();
System.out.println("First: " + b.a); // e.g. after serialization
Field f = b.getClass().getDeclaredField("a");
f.setAccessible(true);
f.set(b, 6); // e.g. putting back your cache
System.out.println("Second: " + b.a); // wow: it has a value!
}}
Reflexive means x.equals(x) should return true
Compiler will catch the error if you try to reference an object member from a sub-class reference.
We aleady know this: any subclass can be referenced by a parent-class/interface reference.
Virtual method invocation only works for methods, not instance variables. For instance variables, Java actually looks at the type of the reference and calls the appropriate variable. This makes each reference call a different class’s instance variable
Know what the contract between hashCode and equals IS:
1) If two objects are equal, then they must have the same hash code.
2) If two objects have the same hash code, they may or may not be equal.
When implementing Comparable, you implement the compareTo() method.
.compareTo(String other)
Any class implementing a compareTo method should implement Comparable!!
Creating a TreeSet from a ArrayList will throw away dupes and order the integers.
public static TreeSet getSort (ArrayList list){
return new TreeSet(list);
}
Given need to sort longest string first:
public int compare(String s1, String s2) {
return s2.length() - s1.length(); // returns negative when s1 is longer
}
DEDUCTION: re-study this: https://repl.it/JoVN/21
Normally we see public class News<Whatever> { //body }
But these are also ok:
public class News<Object>
public class News<News>
Be careful of questions initializing a static variable from a instance variable. Not!
An instance of a anonymous inner class can't be created without a 'new' keyword. Don't be fooled again. NOTE: the anonymous class extends the abstract class here and it works! https://repl.it/JoWY/2
abstract class Person {
abstract void eat();
}
class TestAnonymousInner {
public static void main(String args[]){
Person p = new Person() {
void eat(){System.out.println("nice fruits");}
};
p.eat();
}
}
ClassName.this.fieldName is how you would access a enclosing class field from an inner class. Any "instantiated inner class" object first needed the outer class object to be instantiated, therefore when calling ClassName.this references that superclass instance even when its from the inner class body. This "looks like" a static field accessor sorta.
An interface can still be functional if it has a default and/or static methods in it, as long as there is just one non-default, non-static abstract method.
Since package-private is a more restrictive access than protected, the override of a protected method (without specifying a modifier) is invalid and the code does not compile. You can't give broader access on the override.
An enum and static inner class can define static methods. The other types of inner classes cannot define static methods because they work as instances. Note: interfaces and abstract classes can define static methods but those cant be instantiated anyway.
Since a static nested class cannot refer directly to instance variables or methods defined in its enclosing class, it can use them only through an object reference, it's safe to declare static methods in a static nested class.
There is no such thing as a static inner class: An inner class is by definition non-static (JLS8, 8.1.3) but you can have a "static nested class".
I Repeat: Member inner classes cannot include static methods or variables.
My tests of the inner class behavior above: https://repl.it/JpFe/46 !!!
Java was updated to include default interface methods in order to support backward compatibility of interfaces. By adding a default method to an existing interface, we can create a new version of the interface, which can be used without breaking the functionality of existing classes that implement an older version of the interface
An overridden method may not throw a broader checked exception than it inherits.
I repeat: an anonymous inner class may implement at most one interface
Here is an example showing how we implement Runnable interface without using the key word 'implements': inferred by the 'new' keyword via anonymous usage:
new Runnable() {
public void run() {}
}
abstract interface methods are public by default, be careful when overriding as package-private, which wont compile
!!
if an enum contains an abstract method, then every enum value must include an override of this abstract method!!!!
In a case statement , 'case EnumClass.Whatever:' is not allowed! Case statement must use a effectively final variable and an enum is not final.
enum DaysOff { Thanksgiving, Christmans, Easter }
class Main {
public static void main(String... args) {
final DaysOff input = DaysOff.Thanksgiving;
switch ( input) {
default:
case DaysOff.Thanksgiving: //error: an enum switch case label must be the unqualified name of an enumeration constant
System.out.println("Thanks");
}
}
}
An enum can't be final, because the compiler will generate finalized subclasses (not final vars) for each enum entry that the programmer has explicitly defined an implementation for.
Moreover, an enum where no instances have their own class body is implicitly final, by JLS section 8.9.
the Enum class is abstract because you have to be able to extend it. But, under the hood, the actual enums that extend it get defined by the compiler as final classes (not final variables).
.hashCode never takes a parameter! dont be fooled!
An object is required to return the same value for repeated calls to hashCode(), if the object has not changed.
Also, equality must be reflexive, it cannot return false if the same object is passed
For an immutable class, if the class isn't itself final, then the getter methods must be, otherwise someone can override them.
If two instances of a class have the same hash code, they might or might not be equal. The reverse is not true: If two objects are equal, they must have the same hash code in order to comply with the contracts of these methods.
The compiler wont tell you: Based on the rules of equals(), if null is passed in, the result must be false.
!! Be careful of questions about casting and the question is asking what will fail at compile time rather than runtime. We know that classes downcast to a subclass wont fail until runtime with a ClassCastException.
NOTE: Generally, downcasting is not a good idea. You should avoid it so you don't end up with the runtime exception. If you use it, you better include a check:
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
}
class Building {}
class House extends Building {}
class Main {
public static void main(String[] args) {
Building b = new Building();
House h = new House();
Building bref = new House();
//Building p = (House)b; //ClassCastException at RUNTIME: Building cannot be cast to House (down-cast)
//House q = (Building)h; //compiler error: incompatible types: Building cannot be converted to House: so,
// upcast to building is ok but compiler check wont allow the down-cast reference
Building r1 = (Building)bref; // upcast is ok
Building r2 = (Building)h; // upcast is ok
House s = (House)bref; // object ref is really a house so this is ok
}
}
On questions like this one:
1. watch out for downward object references! compiler wont like it!
2. watch out for down-cast that only gets caught at runtime!
- (X instanceof Collection) will compile if the X doesn't extend Collection, because its an interface that could possibly be implemented in future code changes. It will just fail at runtime.
- (X instanceof ArrayList) wont compile because its not an interface
Java Singleton class must have a private default constructor to prevent instantiation. Members must be static, not necessarily final (as a immutable class would have)?
As with any ExecutorService, the fork/join framework distributes tasks to worker threads in a thread pool. The fork/join framework is distinct because it uses a work-stealing algorithm. Worker threads that run out of things to do can steal tasks from other threads that are still busy. If you had something like multiple threads waiting on http response, then other threads could steal cpu cycles while the http threads wait. (see 'ExecutorService.newWorkStealingThreadPool(4);' )
You can .stream a List of futures!! This is obvious after pointing it out :
ExecutorService executor = Executors.newWorkStealingPool();
List < ContentDuration > results = executor.
invokeAll(callables).stream()
.map(future - > {
try {
return future.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e); //convert checked exceptions to runtime
}
}).collect(Collectors.toList());
OR do this instead: futures.stream().allMatch(Future::isDone)
Yes, a lambda can be within a lambda (example from https://github.com/Workable/java-error-handler ) . I don't think the exam requires that we know this. Code like this usually has a no-op lambda like x -> x . Function.identity() does the same thing as x -> x :
ErrorHandler
.defaultErrorHandler()
.bind("offline", errorCode -> throwable -> {
return throwable instanceof UnknownHostException || throwable instanceof ConnectException;
})
import java.sql.*;
// using Docker MySQL image listening on 3306 locally
public class JdbcTest {
private static String dbAddress = "jdbc:mysql://localhost/docker?user=root&password=password";
private static String createTable = "CREATE TABLE IF NOT EXISTS PersonsNew (ID int, LastName varchar(255), "
+ "FirstName varchar(255), Address varchar(255), City varchar(255), TS TIMESTAMP DEFAULT CURRENT_TIMESTAMP);";
public static void main(String[] args) {
try ( Connection conn = DriverManager.getConnection(dbAddress); Statement stmt = conn.createStatement() )
{
stmt.execute(createTable);
stmt.executeUpdate("INSERT INTO PersonsNew VALUES (1, 'Test', 'First', 'Address', 'City', CURRENT_TIMESTAMP)");
ResultSet rs1 = stmt.executeQuery("Select count(*) from PersonsNew");
rs1.next();
System.out.println("Size: "+ rs1.getInt(1));
rs1.close();
ResultSet rs2 = stmt.executeQuery("Select * from PersonsNew");
while (rs2.next()) {
System.out.println(rs2.getDate(6) + " " + rs2.getTime(6));
}
rs2.close();
} catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
}
}
Remember: SQLException is a checked exception.
Using path.relativize results in a Path object which contains .. chars, such as abs1.relativize(abs2)
Using path.relativize, both paths must be absolute or both paths must be relative !!
Using path.resolve, such as abs1.resolve(rel1), results in abs1 + rel1
Using path.resolve, such as abs1.resolve(abs2), results in just a copy of abs2 !!
Using path.normalize(), will remove redundant info from path, as you might expect
import java.io.File;
public class FileExample {
public static void main(String[] args) throws Exception {
File file = new File("/TEMP/../TEMP/myfile.txt");
System.out.println("ABS: " + file.getAbsolutePath());
System.out.println(" TO: " + file.toPath());
System.out.println("GET: " + file.getPath());
System.out.println("CAN: " + file.getCanonicalPath());
System.out.println("REAL: " + file.toRealPath(LinkOption.NOFOLLOW_LINKS));
}
}
ABS: C:\TEMP\..\TEMP\myfile.txt
TO: \TEMP\..\TEMP\myfile.txt
GET: \TEMP\..\TEMP\myfile.txt
CAN: C:\TEMP\myfile.txt
REAL: ?
Path.toRealPath() will throw java.nio.file.NoSuchFileException if the file does not exist (Javadoc: Returns the real path of an existing file.)
File.getCanonicalPath() will not throw an exception if the file does not exist (it will only throw IOException if the file name itself is invalid and/or contains a '\0' char in it).
NOTE: IOException - If an I/O error occurs, which is possible because the construction of the canonical pathname may require filesystem queries
import java.util.*;
import java.nio.file.*;
public class Test {
public static void main(String[] args) {
Path path1 = Paths.get("../ClientNotes");
Path path2 = Paths.get("../Shots");
System.out.println(path1.relativize(path2)); //prints ../hsq-5659.txt
System.out.println(path2.relativize(path1)); //prints ../hd-1845.txt
}
}
These are ok:
final Collection<? extends Runnable> example1 = new ArrayList<Runnable>(); // co-variant
final Collection<? extends Runnable> example2 = new ArrayList<TimerTask>();
final Collection<? super Runnable> example3 = new ArrayList<Runnable>(); // contra-variant
final Collection<? super Runnable> example4 = new ArrayList<Object>();
import java.util.*;
class Main { // where Thread implements Runnable
public static void main(String[] args) {
final Collection<? super Runnable> example3 = new ArrayList<Runnable>(); // contra-variant
//final Collection<? super Runnable> example3 = new ArrayList<Thread>();
//error: incompatible types: ArrayList<Thread> cannot be converted to Collection<? super Runnable>
}
}
A LinkedHashMap keeps the keys in the order they were inserted, while a TreeMap is kept sorted via a Comparator or the natural Comparable ordering of the elements.
TreeMap has O(log n) performance for containsKey, get, put, and remove, according to the Javadocs, while LinkedHashMap is constant-time O(1) for each
The Set interface does not provide any ordering guarantees.
It's sub-interface, SortedSet, represents a set that is sorted according to some criterion. In Java 6, there are two standard containers that implement SortedSet. They are TreeSet and ConcurrentSkipListSet.
In addition to the SortedSet interface, there is also the LinkedHashSet class. It remembers the order in which the elements were inserted into the set, and returns its elements in that order.
Concerning LinkedHashSet: looking at the source of the HashSet constructor, it's a special constructor that makes the backing Map a LinkedHashMap instead of just a HashMap (as we have in HashSet).
HashSet.contains(Object) operates in O(1) constant-time ; so, if you need to call contains a lot, use this
Use HashSet when you write a lot
Use LinkedHashSet if you read a lot since LinkedHashSet is a little slower on insertions; maintains insertion order
SortedSet if you need sorted
Performance of collections: http://infotechgems.blogspot.com/2011/11/java-collections-performance-time.html
Navigable - provides .lowerKey, .higherKey, .ceilingKey, .floorKey
Sorted - provides .first, .last, .entrySet , & .comparator (returns null when natural ordering is being used)
Ordered - not the same as sorted
Comparator.comparing(Student::getAge) would sort age lowest to highest
Natural reverse order: Comparator.reverseOrder()
Customized reverse order: Comparator.comparing(Student::getAge).reversed() - age highest to lowest
WHY LinkedBlockingQueue ?
A: if you have 2 threads, one thread producing .put calls at an interval, and another consumer thread that is trying to call .take(), then the consumer thread needs to be able to block until a putted item is available.
LinkedBlockingQueue lacks a push method because its not a stack: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedBlockingQueue.html
.flatMap creates a new non-parallel stream, even if the inputs were parallel
- during operation it calls: result.sequential().forEach(downstream);
.concat creates a parallel stream if either of the input streams are parallel
import java.lang.Math;
public class HelloWorld {
public static void main(String[] args)
{
long what = (long)Math.sqrt(12);
System.out.println("long "+ what); //prints 'long 3'; rounds down on conversion
}
}
// some would say I am over-complicating this...
In context of Comparable.compareTo(Object a):
this.id - a.id sorts ascending
- when 'this/calling' object is smaller than a, return -
- when 'this/calling' object is larger than a, return +
- Paraphrase: int result of .compareTo(Object a), having this.age - a.age, will sort
higher int return values to the top, which are the smaller compared values
- Paraphrase: where self.compareTo(other), then return positive when other is sorted
towards top, being smaller after comparison
- Paraphrase: if self.age is higher, return positive when other is younger, sorting
them above me
- Un-intuitive because smaller values sort to the top because of higher int return value from .compareTo method
Reverse: a.id - this.id sorts descending
See: https://repl.it/JpWN/26
public class CompareStringsTest
{
public static void main(String[] args)
{
String one = "one";
String two = "two";
System.out.println("One compared to two: " + one.compareTo(two)); // -5
System.out.println("Two compared to one: " + two.compareTo(one)); // +5 - two is greater than one (by alphabetical order)
}
}
!! about semantics of Collections:
ArrayList and LinkedList store ordered collections of things, and don't line up with the use-cases of Stack or Queue directly. Stacks and Queues are in a sense buffers of data, whereas the semantics of a List typically make it such that it's a store of data; nothing is stopping you from using a List to implement a Stack or a Queue.
LIFO (stack) is push/poll/peek, FIFO (queue) is offer/poll/peek
HashSet allows a 'null value' not 'null values'. it allows only 1 null value per 1 HashSet Object
Why Set interface does not allow null elements?
HashSet contract specifies that remove() return true if the specified object existed and was removed. To do this, it uses the wrapped HashMap#remove() which returns the removed value. If you were to store null instead of an object, then the call to HashMap#remove() would return null, which would be indistinguishable from the result of attempting to remove a non-existent object, and the contract of HashSet.remove() could not be fulfilled.
You can tell the difference between methods in ArrayDeque or LinkedList vs. methods in Queue and Deque because the latter methods are shorter: .add, .remove, .poll, .pop, .peek VS. .removeLast, .offerLast, .peekFirst, etc.
On the other hand, where Queue has some simple short methods, Deque adds some similar methods, with more verbose names, such as .peekFirst instead of .peek.
A reifiable type is a type whose type information is fully available at runtime. This includes primitives, non-generic types, raw types, and invocations of unbound wildcards.
Non-reifiable types are types where information has been removed at compile-time by type erasure — invocations of generic types that are not defined as unbounded wildcards. A non-reifiable type does not have all of its information available at runtime. Examples of non-reifiable types are List<String> and List<Number>; the JVM cannot tell the difference between these types at runtime. As shown in Restrictions on Generics, there are certain situations where non-reifiable types cannot be used: in an instanceof expression, for example, or as an element in an array.
reify - existing as a concrete material object
When the compiler encounters a varargs method, taking for example List<String>, it translates the varargs formal parameter into an array. However, the Java programming language does not permit the creation of arrays of parameterized types. In the method ArrayBuilder.addToList, the compiler translates the varargs formal parameter T... elements to the formal parameter T[] elements, an array. However, because of type erasure, the compiler converts the varargs formal parameter to Object[] elements, not String[]. Consequently, there is a possibility of heap pollution.
there are certain situations where non-reifiable types cannot be used: in an instanceof expression, for example, or as an element in an array
Don't create a CyclicBarrier of 3 when you only have 2 threads in your pool. Your 2 threads will hang on the .await call and the 3rd .away won't get called. Even if you submitted 12 tasks to the ExecutorService.
ObjectInputStream.readObject requires casting.
Even if you can't modify the Bicycle interface, to force users to implement compareTo at compile time, you can extend it.
public interface ComparableBicycle extends Comparable<ComparableBicycle> {
}
NOTE: this isn't extending an interface, as we know interfaces are capable of doing
When using Collections.syncronizedList, make sure the reference you get is not used in an iterator or for loop unless you also use the synchronized keyword on the object.
For a class to be immutable:
Mark the class final
Any methods that get a object ref, like a list, should return a copy and not give access to the list
Mark class members final (if class itself is not final; or do it anyway)
No setter methods
.createStatement( ResultSet TYPE, ResultSet CONCURRENT mode)
Calling .get on an empty Optional throws a NoSuchElementException. Call opt.isPresent before you try to call opt.get
So I would use Optional.of only when null is an error, which should be found early, otherwise if null might be an expected return value, you could use Optional.ofNullable
Runtime Exceptions: NullPointerException, ArithmeticException, ConcurrentModificationException, nio:FileSystemNotFoundException, IllegalArgumentException, SecurityException, ArrayStoreException, DateTimeException, util: MissingResourceException, IllegalStateExcepton, UnsupportedOperationException, ClassCastException, ArrayIndexOutOfBoundsException, NumberFormatException
Checked Exceptions: ParseException (java.text), IOException, FileNotFoundException, NotSerializableException, SQLException,
Checked exceptions always need to be handled. Be careful because code won't compile.
Object objectElement = new Object();
List<String> stringList = new ArrayList<String>();
Object theElement = addAndReturn(objectElement, stringList); // compiler error. cant put object in a String list.
Don't put a non-Closeable (or non-AutoCloseable) in a try-with-resources statement. It won't compile.
EnumClass.values() returns a primitive array, not a List
LinkedList.clone is a shallow copy, or copy of the reference only.
LinkedList: Doubly-linked list implementation of the List and Deque interfaces. Implements all optional list operations, and permits all elements (including null).
LinkedList has both .offer and .push , just like a Deque .
Creating a new LinkedList. LinkedList doesn't contain the peek(), empty() and search() methods, so it's not a fully-fledged stack.:
LinkedList list = new LinkedList();
list.add("Hello"); list.add(2); list.add("Chocolate"); list.add("10");
list.remove();
System.out.println("LinkedList:" + list); // LinkedList:[2, Chocolate, 10]
ArrayDeque is memory efficient since you don't have to keep track of next node unlike in Linked List. ArrayDeque is Resizable-array implementation of the Deque interface. ... This class is likely to be faster than Stack when used as a stack, and faster than LinkedList when used as a queue. Array deques have no capacity restrictions; they grow as necessary to support usage. They are not thread-safe; in the absence of external synchronization, they do not support concurrent access by multiple threads. Null elements are prohibited.
Example: ArrayDeque<Integer> wontCompile = new LinkedList<>(); //wont compile, they are different
Explanation: although ArrayDeque<E> and LinkedList<E> have both implemented Deque<E> Interface, the ArrayDeque uses basically Object array E[] for keeping the elements inside its Object, so it generally uses index for locating the head and tail elements.
In a word, it just works like Deque (with all Deque's method), but however uses array's data structure. LinkedList does not use underlying array data structure: It's a series of instances of a private nested class Entry, which has next, previous and element references. As regards which one is better, depends on how and where you use them.
Deque extends Queue - In the case of ArrayDeque:
First Element (Head) Last Element (Tail)
Throws exception Special value Throws exception Special value
Insert addFirst(e) offerFirst(e) addLast(e) offerLast(e)
Remove removeFirst() pollFirst() removeLast() pollLast()
Examine getFirst() peekFirst() getLast() peekLast()
This interface extends the Queue interface. When a deque is used as a queue, FIFO (First-In-First-Out) behavior results. Elements are added at the end of the deque and removed from the beginning. The methods inherited from the Queue interface are precisely equivalent to Deque methods as indicated in the following
table:
CAPTION: Comparison of Queue and Deque methods
Queue Method Equivalent Deque Method
add(e) addLast(e)
offer(e) offerLast(e)
remove() removeFirst()
poll() pollFirst()
element() getFirst()
peek() peekFirst()
Deques can also be used as LIFO (Last-In-First-Out) stacks. This interface should be used in preference to the legacy Stack class. When a deque is used as a
stack, elements are pushed and popped from the beginning of the deque. Stack methods are precisely equivalent to Deque methods as indicated in the table
below:
CAPTION: Comparison of Stack and Deque methods
Stack Method Equivalent Deque Method
push(e) addFirst(e)
pop() removeFirst()
peek() peekFirst()
Note that the peek method works equally well when a deque is used as a queue or a stack; in either case, elements are drawn from the beginning of the deque.
This interface provides two methods to remove interior elements, removeFirstOccurrence and removeLastOccurrence.
Unlike the List interface, this interface does not provide support for indexed access to elements!!
While Deque implementations are not strictly required to prohibit the insertion of null elements, they are strongly encouraged to do so. Users of any Deque implementations that do allow null elements are strongly encouraged not to take advantage of the ability to insert nulls. This is so because null is used as a special return value by various methods to indicated that the deque is empty.
Deque implementations generally do not define element-based versions of the equals and hashCode methods, but instead inherit the identity-based versions from class Object.
Stack<Integer> stack = new Stack<Integer>();
stack.push(17); // autoboxing (int -> Integer)
int a = stack.pop(); // unboxing (Integer -> int)
import java.util.*;
public class Structures
{
public static void main(String[] args)
{ // all these compile OK
List<String> mylist = new ArrayList<>();
ArrayDeque<Integer> traditionalStack = new ArrayDeque<>(); // a full fledged doubled ended queue
Stack<Integer> stack = new Stack<Integer>();
Deque<Integer> doubleEndedStack = new LinkedList<>();
List<Integer> singleEndedStack = new LinkedList<>();
Queue<Integer> queue = new ArrayDeque<>(); // this is an arraydeque object but limited to queue methods by reference
Queue<String> stringQueue = new LinkedList<>();
List<String> list = Collections.synchronizedList(new LinkedList<>());
}
}
HashMap and HashSet are entirely different constructs. A HashMap is an implementation of Map. A Map maps keys to values. The key look up occurs using the .hashCode method in a HashSet, but it's not a key-pair construct.
HashSet gives you an O(1) [constant time] contains() method but doesn't preserve order.
ArrayList contains() is O(n) [linear time] but you can control the order of the entries.
Array if you need to insert anything in between, worst case can be O(n), since you will have to move the data down and make room for the insertion. In Set, you can directly use SortedSet which too has O(n) too but with flexible operations.
I believe Set is more flexible.
Will wait for deck to be in proper state before letting go (can throw InterruptedException) :
BlockingDeque.putFirst , BlockingDeque.putLast
BlockingDeque.takeFirst, BlockingDeque.takeLast
.push - to front of deque, returns void
.offer - to end of queue - returns boolean
only .add and .offer return boolean value
Files class throws an exception if the file where the path points does not exist.
Files.find throws IOException if it cant reach the starting file
Path start = Paths.get(""); //this seems to be ok though
System.out.println(start.toAbsolutePath());
Files.find takes a BiPredicate
Stream<Path> find(Path start, int maxDepth, BiPredicate<Path,BasicFileAttributes> matcher, FileVisitOption... options) throws IOException
// when using it, you aren't required to search by using the basicFileAttributes object. that is just optional
Stream<Path> fs = Files.find(startingPath, Integer.MAX_VALUE,
(path, basicFileAttributes) -> path.toFile().getName().matches(".*.pom")
);
Another example, using try-with-resources syntax on a stream ! :
Path start = Paths.get("");
int maxDepth = 5;
try (Stream<Path> stream = Files.find(start, maxDepth, (path, attr) -> String.valueOf(path).endsWith(".js"))) {
String joined = stream
.sorted()
.map(String::valueOf)
.collect(Collectors.joining("; "));
System.out.println("Found: " + joined);
}
Files.lines() returns a lazy stream, just like Files.find, but Files.readAllLines() returns a non-lazy list.
SQL ResultSet is a 1-based index.
Two objects that return true for .isEquals will/should always return same hashcode but the opposite is NOT TRUE
A "local class", or a Class within the local context of a method, CAN exist within a static or non-static method
A local class has access to the members of its enclosing class.
Local classes are similar to inner classes because they cannot define or declare any static members. A local class can have static variables provided that they are constant variables, or effectively final.
Local classes in static methods, such as the class PhoneNumber, which is defined in the static method validatePhoneNumber, can only refer to static members of the enclosing class.
Local classes are non-static because they have access to instance members of the enclosing block. Consequently, they cannot contain most kinds of static declarations: You cannot declare an interface inside a block; interfaces are inherently static.
An object with a interface or supertype ref refers to the original underlying object, so don't try to cast it to a sibling type or you'll get a ClassCastException at runtime, that is down-casting.
Downcasting: If you have a reference variable that refers to a subtype object, you can assign it to a reference variable of the subtype. You must make an explicit cast to do this, and the result is that you can access the subtype's members with this new reference variable.
Upcasting: You can assign a reference variable to a supertype reference variable explicitly or implicitly. This is an inherently safe operation because the assignment restricts the access capabilities of the new variable.
instanceof works on a interface
instanceof will throw a COMPILE-TIME error against types that don't extend
Outer.Inner in = new Outer().new Inner()
enum must have semicolon only if anything else is in the enum
public class HelloWorld {
public void toddle() throws Exception {};
class BabyHelloWorld extends HelloWorld {
public void toddle() { System.out.println();} // could also put a 'throws Exception {}' here also
}
}
Virtual method invocation says that the subclass method gets called at runtime rather than the type in the variable reference. For variables/members, this is not the case.
FourLegged f = new BabyRhino();
f.walk // is the value of FourLegged.walk, not BabyRhino.walk
f.walkAction() // calls BabyRhino.walkAction() virtually
// remember, parameter is an object
@Override
public boolean equals(Object obj) {
....
Parenthesis is required on a lambda when data type is used on the left side of expression.
Singleton cannot be private or protected. Must be public or default.
Singleton constructor being protected or private defeats direct instantiation of the object. Usually there is a public static .getInstance method or something.
A singleton instanced can be replaced with a encapsulated setter method: thats ok because its not immutable
Constructor of a singleton class must be private!!
Singleton ensures only one instance of object in memory
Singleton builder/factory must be a public static method to get global instance
Spring beans are singletons usually, as defined in Spring .xml config
Yes, Java 8 interfaces enable some limited form of multiple inheritance.
Interface methods cannot be final.
Interface can declare a constant variable, using static final which is different from an instance variable.
CH.3
import java.util.*;
class Main {
public static void main(String[] args) {
doIt("second");
}
public static void doIt(String type) {
StringBuilder sb;
switch (type) {
case "first":
sb = new StringBuilder("whatever");
break;
case "second":
Optional<Integer> optional = Optional.of(0);
optional.ifPresent(value -> sb = new StringBuilder(value));
}
}
}
Don't modify outside variable during a lambda! error message: "variable used in lambda should be effectively final".
Don't redfine a variable on a lambda into a new Type!! :
import java.util.concurrent.atomic.*;
public class HelloWorld
{
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5);
AtomicInteger ordinal = new AtomicInteger();
list.forEach(s -> {String s = new String();}); // dont change variable to a new type!!!
}
}
Return the result of the first service that responds:
Optional<Result> o = Stream.<Supplier<Optional<Result>>>of(
()->serviceA(args),
()->serviceB(args),
()->serviceC(args),
()->serviceD(args))
.map(Supplier::get)
.filter(Optional::isPresent) // filter on Optional::isPresent when Supplier returns optional/s !! cool
.map(Optional::get)
.findFirst();
Static methods defined in an interface must have a body.
Object Composition has no notion about inheritance/polymorphism.
Inheritance is an "is-a" relationship. Composition is a "has-a".
Don't try to add a primitive Int nor an Integer to a List<String> object. It wont compile.
This is OK:
List<String> list = new Vector<String>();
Vector, ArrayList, and LinkedList are siblings using the List interface.
HashSet<? super ClassCastException> set = new HashSet<Exception>(); // ok lower bound
Map<String, ? extends Number> hm = new HashMap<String, Integer>(); // ok
ArrayList<? super Date> list = new ArrayList<Date>(); // ok
Vector<? extends Number> list = new Vector<Integer>(); // ok
List<? super IOException> ioexception = new ArrayList<Exception>();
//ioexception.add(new Exception("Wont Compile!"));
ioexception.add(new IOException("Compiles!"));
ioexception.add(new InterruptedIOException("Compiles!"));
ioexception.add(new SocketTimeoutException("Compiles!"));
List<? super InterruptedIOException> intexception = new ArrayList<Exception>();
//intexception.add(new Exception("Wont Compile!"));
//intexception.add(new IOException("Wont Compile!"));
intexception.add(new InterruptedIOException("Compiles!"));
intexception.add(new SocketTimeoutException("Compiles!"));
import java.util.*;
public class Main {
public static void main(String[] args) {
//String s = newList(); // wont compile
//System.out.println(s);
List<Integer> l = Main.<ArrayList<Integer>>newList(); // this compiles and works well
System.out.println(l);
}
private static <T extends List<Integer>> T newList() {
return (T) new ArrayList<Integer>();
}
}
HashSet does not retain order.
GIVEN: natural sort is numbers, upper, then lower
import java.util.*;
public class HelloWorld {
public static void main(String[] args) {
TreeSet<String> tree = new TreeSet<String>();
tree.add("one");
tree.add("One");
tree.add("ONE");
System.out.println(tree.ceiling("On")); // prints 'One'
}}
TreeSet .ceiling: The method call returns the least element greater than or equal to e, or null if there is no such element.
http://tutorials.jenkov.com/java-collections/navigableset.html#ceiling
https://repl.it/KIVG/7
https://repl.it/KIVG/20
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet <Integer>treeadd = new TreeSet<Integer>();
treeadd.add(12);
treeadd.add(11);
treeadd.add(16);
treeadd.add(15);
System.out.println("Ceiling value for 13: "+treeadd.ceiling(13)); // prints 15
}
}
Java Map interface: .get , .put , .putAll, V .remove , .clear , .values
Java List interface: .add , .addAll, boolean remove(Object), V remove(int),
String[] y = list.toArray(new String[0]);
Object[] z = list.toArray();
NOTE: using a Comparable lambda would be silly since the point of Comparable is to implement it inside the object being compared
public interface Comparable<T> {
int compareTo(T o); // 1 parameters, we would need a bifunction to use as a lambda!
}
Return a negative value if THIS object is SMALLER than the other object
Return 0 (zero) if this object is equal to the other object.
Return a positive value if THIS object is LARGER than the other object.
public interface Comparator<T> {
int compare(T object1, T object2); // 2 parameters!!!!
}
Return a negative value if object1 is smaller than object2 // the pattern is similar to Comparable, as you can see
Return 0 (zero) if objec1 is equal to object2.
Return a positive value if object1 is larger than object2.
public class MyComparator<Employee> implements Comparator<Employee> {
public int compare(Employee emp1, Employee emp2){
return emp1.getSalary() - emp2.getSalary(); // ascending order
}
}
Remember that sorting id - arg.id sorts in ascending order and arg.id - id sorts in descending order.
Sort descending: personList.sort((a,b)->b.getName().compareTo(a.getName()));
Sort descending: Collections.sort(personList, (Person a, Person b) -> b.getName().compareTo(a.getName()));
NOTE1: This can be CONFUSED by the fact that since .sort takes a Comparator , and within that lambda, we use the Comparable interface of the String object itself, using the .compareTo method.
NOTE2: It wouldnt make sense to have the lambda .sort method to take a single arg Comparable interface because then there isn't anything to compare to
Remember this? list.stream().sorted(Comparator.reverseOrder())
import java.util.*;
public class Main implements Comparable<Main>, Comparator<Main> {
private int num;
private String text;
Main(int n, String t) {
this.num = n;
this.text = t;
}
public String toString() { return "" + num; }
public int compareTo(Main s) {
return this.text.compareTo(s.text);// sorts in alphabetic order
}
public int compare(Main s1, Main s2) {
return s1.num - s2.num; //sorts in numeric order
}
public static void main(String[] args) {
Main s1 = new Main(88, "a");
Main s2 = new Main(55, "b");
TreeSet<Main> t1 = new TreeSet<>();
t1.add(s1); t1.add(s2);
// the diff is here, TreeSet instance passed
// works whether you pass s1 or s2 but NOT if you don't
// Constructs a new, empty tree set, sorted according to the specified comparator.
// where s1 or s2 is a comparator, not actual data!!
// TreeSet constructor takes 1 of 3 things: SortedSet, Collection, or Comparator
// in this case Main does NOT extend Collection!!
TreeSet<Main> t2 = new TreeSet<>(s2); // <-- see, we passed a Comparator interface here, as the method wanted!!
t2.add(s1); t2.add(s2);
System.out.println(t1 + " " + t2); // prints [88, 55] [55, 88]
}
}
//https://repl.it/KIVk/11
Arrays.binarySearch(sortedarray,searchVal)
A binary search will return a undefined -1 value when search object is sorted in reverse.
Most of the time a unsorted array will return a undefined value on a binary search, but NOT always.
Trying to sort a primitive array using 'Arrays.sort(intArr, Collections.reverseOrder())' wont compile.
A unsorted array will return a binary search result that is incorrect.
When a undefined value is returned, it is usually 1, but since unsorted arrays can sometimes cause a non-null undefined result, in the example below, the return value of 3 really is a undefined value even though it appears to return a correct value.
https://repl.it/KIWL/6
import java.util.*;
class Main {
public static void main(String[] args) {
//NOTE: returning a 3 is really a invalid result, but it appears to be correct.
// You can prove it by running against another intArr[]
Integer intArr[] = {30,20,5,12,55}; // returns 3
//Integer intArr[] = {30,20,5,12,55,8,7,0,2}; // returns -1
//Arrays.sort(intArr); //a
//Arrays.sort(intArr, Collections.reverseOrder()); //b
System.out.println("The sorted int array is: ");
for (int number : intArr) {
System.out.println("Number = " + number);
}
int searchVal = 12;
int retVal = Arrays.binarySearch(intArr,searchVal);
System.out.println("The index of element 12 is : " + retVal); // prints 1
}
}
Be careful of questions which define a class name that is the same as a "type letter", like R, T, U, V, etc.
class D<C> would be invalid where D is a class extending C!
LinkedList implements Deque and Queue:
Remove from a LinkedList:
.clear,
.remove(Object) returns boolean,
.remove(int) returns T object,
.remove() - removes the head/first-element returns object
from HashMap: has a .containsKey and .containsValue method but not .contains
from HashMap: void .forEach(BiConsumer<? super K,? super V> action) // 2-arg constructor because of Key+Value
from Iterable: void .forEach(Consumer<? super T> action)
Collection: boolean .removeIf(Predicate<? super E> filter)
AbstractSequentialList: this interface backed by a "sequential access" data store (such as a LinkedList). For random access data (such as an array[]), AbstractList should be used in preference to this class (just as ArrayList currently does).
import java.util.*;
//https://repl.it/KIWb/3
public class HelloWorld {
public static void main(String[] args) {
Set<String> s = new HashSet<>();
s.add("lion");
s.add("tiger");
s.add("bears");
s.forEach(System.out::println); // Consumer
//s.forEach(() -> System.out::println); //BAD, not a single param consumer
//s.forEach((s) -> System.out.println(s)); //BAD, don't redefine s, which is already a local scope var
}}
import java.util.*;
public class HelloWorld {
public static void main(String[] args) {
Map<String,String> s = new HashMap<>();
s.put("1","lion");
s.put("2","tiger");
s.put("3","bears");
s.forEach( (key, value) -> { System.out.println( "Key: " + key + "\t" + " Value: " + value ) ;}); // BiConsumer
}}
Basic merge: map.merge(key, msg, String::concat)
Merging 2 maps example:
Map<T, Set<U>> merged = Stream.of(first, second)
.map(Map::entrySet)
.flatMap(Set::stream)
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> {
HashSet<U> both = new HashSet<>(a);
both.addAll(b);
return both;
}));
// Another example showing use of entrySet().stream and comparing .of and .concat
Stream.of(first, second).flatMap(m -> m.entrySet().stream())
.collect(...);
Stream.concat(first.entrySet().stream(), second.entrySet().stream())
.collect(...);
import java.util.*;
class Main {
public static void main(String[] args) {
merge1();
computeIfPresent1();
compute1();
}
static void merge1() {
System.out.println("-- Merge1:");
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 10); map.put(2, 20); map.put(3, null);
map.merge(1, 3, (a,b) -> a + b); // uses BiFunction
map.merge(3, 3, (a,b) -> a + b);
System.out.println(map); // prints {1=13, 2=20, 3=3}
}
static void computeIfPresent1() {
System.out.println("-- ComputeIfPresent1:");
Map<Integer,String> nameForId = new HashMap<>();
nameForId.computeIfPresent(1, (key, oldVal) -> {
System.out.printf("BiFunction(%d,%s) for new%n", key, oldVal);
return "JX";
});
System.out.println("After add new: " + nameForId);
nameForId.put(1, "JX");
nameForId.computeIfPresent(1, (key, oldVal) -> {
System.out.printf("BiFunction(%d,%s) update%n", key, oldVal);
return oldVal.concat("-concatVal");
});
System.out.println("After update: " + nameForId);
nameForId.computeIfPresent(1, (key, oldVal) -> {
System.out.printf("BiFunction(%d,%s) -> null%n", key, oldVal);
return null;
});
System.out.println("After null: " + nameForId);
}
static void compute1() {
System.out.println("-- Compute1:");
Map<String, Integer> map = new HashMap<>();
map.put("A", 11); map.put("B", 12); map.put("C", 13);
System.out.println(map.compute("A", (k, v) -> v == null ? 42 : v + 41)); // prints 42+11=52, uses BiFunction
System.out.println(map); // prints {A=52, B=12, C=13} 52=41+11
System.out.println(map.compute("X", (k, v) -> v == null ? 42 : v + 41)); // prints 42
System.out.println(map); // prints {A=52, B=12, C=13, X=42}
}}
//https://repl.it/KIWy
Java printf Conversion-Characters:
d : decimal integer [byte, short, int, long]
f : floating-point number [float, double]
c/C : character Capital C will uppercase the letter
s/S : String Capital S will uppercase all the letters in the string
h : hashcode A hashcode is like an address. This is useful for printing a reference
n : newline Platform specific newline character- use %n instead of \n for greater compatibility
Make sure stream has a terminal operation or it will not execute. This would be bad:
System.out.println(stream.limit(2).map(x -> x + "2");
Don't re-operate on a stream which already executed its terminal operation.
import java.util.stream.*;
public class HelloWorld
{
public static void main(String[] args)
{
Stream<String> stream = Stream.iterate("", (s) -> s + "1");
stream.limit(2).map(x -> x + "2").forEach(System.out::println);
stream = Stream.iterate("", (s) -> s + "1"); // re-initialize stream again
stream.limit(2).map(x -> x + "2").forEach(System.out::println);
}
}
DoubleStream reduction example:
double sum = widgets.stream()
.filter(w -> w.getColor() == RED)
.mapToDouble(w -> w.getWeight())
.sum(); // .sum is a reduction
//IntStream has reduction ::sum
import java.util.OptionalInt;
import java.util.OptionalDouble;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
IntStream i = IntStream.of(6,5,7,1, 2, 3, 3);
OptionalInt v = i.reduce(Integer::sum); // returns primitive int
if(v.isPresent()){
System.out.println(v.getAsInt());
} else {
System.out.println(v);
}
DoubleStream d = DoubleStream.of(1.2,2.3,4.5);
double x = d.sum();
System.out.println(x);
d = DoubleStream.of(1.2,2.3,4.5);
OptionalDouble y = d.reduce(Double::sum);
System.out.println(y.getAsDouble());
}
}
NOTE1: OptionalInt doesn't have a .getAsLong method nor a .getAsDouble method
NOTE2: DoubleStream and DoubleInt .reduce returns OptionalDouble and OptionalInt
NOTE3: 2-arg constructor of IntStream .reduce will return a primitive int; the 2nd arg is IntBinaryOperator with .applyAsInt method
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
Stream<String> s = Stream.generate(() -> "meow");
Optional<String> opt1 = s.findAny();
if ( opt1.isPresent() )
System.out.println(opt1.get()); // meow
s = Stream.generate(() -> "meow");
Optional<String> opt2 = s.findFirst();
if ( opt2.isPresent() )
System.out.println(opt2.get()); // meow
s = Stream.generate(() -> "meow");
boolean match = s.limit(5).anyMatch(String::isEmpty);
System.out.println(match); //false
}
}
stream.average returns a OptionalDouble :
import java.util.*;
import java.util.stream.*;
public class Test {
public static void main(String args[]) {
OptionalDouble average1 = Stream.of(3,34,76,27,91,23,35)
.mapToDouble(a -> a)
.average();
System.out.println(average1.getAsDouble());
OptionalDouble average2 = Stream.of(3,34,76,27,91,23,35)
.mapToInt(a -> a)
.average();
System.out.println(average2.getAsDouble());
}}
Create your own Averager:
class Averager implements IntConsumer {
private int total = 0; private int count = 0;
public double average() {
return count > 0 ? ((double) total)/count : 0;
}
public void accept(int i) { total += i; count++; }
public void combine(Averager other) { // combiner
total += other.total;
count += other.count;
}}
Then use it:
Averager averageCollect = roster.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.map(Person::getAge)
.collect(Averager::new, Averager::accept, Averager::combine);
System.out.println("Average age of male members: " + averageCollect.average());
Don't call .get() on a numeric Optional, like OptionalDouble, use .getAsDouble instead.
//Be careful not to use post-increment in a Stream: x++ . Use ++x instead.
//If you don't, this will print 11111 instead of 12345 .
import java.util.*;
import java.util.stream.*;
public class Test {
public static void main(String args[]) {
System.out.println(Stream.iterate(1, x -> ++x).limit(5).map(x -> x + "").collect(Collectors.joining()));
}}
Return a Set from a .partitioningBy:
// <T,D,A> Collector<T,?,Map<Boolean,D>> partitioningBy(Predicate<? super T> predicate, Collector<? super T,A,D> downstream)
Map<Boolean, Set<Student>> passingFailing =
students.stream()
.collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD, Collectors.toSet()));
import java.util.*;
import java.util.stream.*;
public class Test {
public static void main(String args[]) {
Stream<String> s = Stream.of("one", "three", "four", "five");
Stream<String> s2 = Stream.of("one", "three", "four", "five");
Map<Boolean, List<String>> p = s.collect(Collectors.partitioningBy(b -> b.startsWith("f")));
System.out.println(p);// prints {false=[one, three], true=[four, five]}
Map<String, List<String>> g = s2.collect(Collectors.groupingBy(b -> b.length() + ""));
System.out.println(g);// prints {3=[one], 4=[four, five], 5=[three]}
}}
Operator interfaces don't have to specify return type because return type is the same as input type:
Function<Integer, Integer> f = x => x*x; is equivilant to UnaryOperator<Integer> u = x -> x *x;
CH.5
Localization resource Java classes that contain objects can't be expressed in a .properties file.
Don't try to add hours to a LocalDate because it doesn't have a time component.
Parsing an invalid date throws a RuntimeException, not a Checked exception. Parsing JSON
import java.util.*;
import java.text.*;
import java.util.stream.*;
public class Test {
public static void main(String args[]) {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy");
String dateInString = "7-Jun-rt"; //java.text.ParseException: Unparseable date: "7-Jun-rt"
try {
Date date = formatter.parse(dateInString);
System.out.println(date);
System.out.println(formatter.format(date));
} catch (RuntimeException e) {
System.out.println("This line probably never will be reached.");
e.printStackTrace();
} catch (ParseException e) {
System.out.println("This is a checked exception.");
e.printStackTrace();
}
}}
import java.util.*;
import java.text.*;
import java.time.*;
public class Test {
public static void main(String args[]) {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy");
String dateInString = "7-Jun-er"; //java.text.ParseException: Unparseable date: "7-Jun-rt"
try {
Date date = formatter.parse(dateInString);
System.out.println(date);
System.out.println(formatter.format(date));
} catch (RuntimeException e) {
System.out.println("1: This line probably never will be reached.");
e.printStackTrace();
} catch (ParseException e) {
System.out.println("1: This is a checked exception."); // reached
e.printStackTrace();
//throw e; // enabling this will stop the code flow; add throws to main method
}
// code continues and prints both exceptions here
try {
LocalDate date1 = LocalDate.of(2018, Month.APRIL, 40);
System.out.println(date1.getYear() + " " + date1.getMonth() + " " + date1.getYear());
} catch (DateTimeException e) { // don't catch a ParseException here, it can't be thrown
System.out.println("2: This is a DateTimeException RUNTIME exception.");
e.printStackTrace();
}
}}
1: This is a checked exception.
java.text.ParseException: Unparseable date: "7-Jun-er"
at java.text.DateFormat.parse(DateFormat.java:366)
at Test.main(Test.java:9)
2: This is a DateTimeException RUNTIME exception.
java.time.DateTimeException: Invalid value for DayOfMonth (valid values 1 - 28/31): 40
at java.time.temporal.ValueRange.checkValidValue(ValueRange.java:311)
at java.time.temporal.ChronoField.checkValidValue(ChronoField.java:703)
at java.time.LocalDate.of(LocalDate.java:248)
at Test.main(Test.java:21)
To compare 2 time zones, subtract the zone associated to each time.
It's ok to create a ZonedDateTime at DST 2:15am. Java will adjust the hour.
Duration.of(60, SECONDS); is the same string value as Duration(1, MINUTE);
Properties.getProperty(key, default) vs. Properties.get(key)
Instant does NOT contain time zone information.
ZonedDateTime.ofInstant(instant, TimeZone.getDefault())
CH.6
A try statement can NEVER omit the braces.
If you use a Closeable , you can only throw a IOException.
If you use AutoCloseable, you can throw any exception type.
Closeable requires implementation to be idempotent: repeated closes dont create any different effect
When enabling assertions, we usually have a -da followed by a -ea
-ea:packate.classname or -ea:package... : three dots for all classes in the package
Java assert is separated from the failure message by a colon character
the boolean condition can be in parenthesis
When re-throwing an exception, you can throw a subclass of a caught exception type. You can't catch a IOException and then throw a new RuntimeException .
In a multi-catch, you can't put both a Exception type and a sub-class of that Exception type.
public class Test {
public static void main(String args[]) throws ParseException {
try{
// nothing
} catch (Exception | RuntimeException e) {
// nothing
}
}}
error: Alternatives in a multi-catch statement cannot be related by subclassing
An exception thrown in a static initialization block throws an ExceptionInitializationError and shows the caused by Exception.
In a Closeable, don't throw Exception. Only IOException would be allowed.
If a method throws IOException, java allows you to catch it with Exception .
import java.io.*;
public class Test {
public static void main(String args[]) {
try{
throw new IOException("Whatever");
} catch (Exception e) {
//nothing
}
}}
Idempotent: clients can make that same call repeatedly while producing the same result
CH.7 - Concurrency
A thread or a Runnable are executed with .start()
(new Thread(new PrintRunnable()).start();
(new PrintRunnableThread()).start();
And, the above are executed asynchronously.
Implementing Runnable, rather than extending Thread class:
1. Allows you to extend another Class
2. Separates implementation of task performed from the Thread executing that task
3. Allows you to pass the Runnable to numerous Concurrency class constructors
4. Doesn't allow you to implement your own Thread behavior
ExecutorService:
1. .submit does the same thing as .execute except that submit() returns an object
2. .execute cannot take a Callable, only a Runnable
3. .execute can take a Runnable but The Future's get method will return null upon successful completion.
4. If you have a ExecutorService and .submit Runnable tasks to it, you are also allowed to submit a .execute Runnable also. The service accepts both, not one or the other.
5. If you start threads on a ExecutorService, don't forget to shut down the service when your done.
Surprisingly, this works:
final long[] longs = {2,4L,6,8};
.parallelStream().sorted().findAny() will return the item from the first thread that finishes, not necessarily the first item in the sorted result.
RecursiveTask and RecursiveAction are related to Fork/Join framework, and is analogous to .execute/.submit on ExecutorService.
RecursiveAction requires us to implement 'void compute' method. .invokeAll is often used with this.
RecursiveTask requires us to implement 'T compute' method
.join() causes the process to wait for threads to join. if placed in the wrong location, this can cause single-threaded performance.
invokeAll() does not return a result. it can take 2 args of ForkJoinTask (usually as new-constructors), or it can take a vararg, or List of ForkJoinTask objects. It works when you expect no result back from the tasks.
.fork() is similar to .submit() method, and adds new task to the pool, returns a asynchronous Future
Calling a recursive method .compute within the same .compute method blocks/waits for the Thread result, which is why we want to Fork and then Join later.
1. fork
2. then .compute + .join
.compute takes no arguments and so class Constructor is often used to setup work.
Basic Fork Join: if the piece of work in .compute is too small to split, do it, and return value immediately so it can be joined later
if the piece of work is large enough to be split
then create a new task with half of that work and fork it off
then wait for calculation of remaining work via .compute call
then join the work of the forked off task
Calling .parallelStream().parallel() will compile and run.
Calling service.submit() twice, one after the other, returns Futures and the task is asynchronous and who finishes first may not be predictable.
// practice this one!!
import java.util.concurrent.*;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
public class CountNumbers extends RecursiveAction {
private int start;
private int end;
public CountNumbers(int start, int end) {
this.start = start;
this.end = end;
}
protected void compute() {
if (start<0) {
return;
} else {
int middle = start + ((end-start) / 2);
System.out.println("[start="+start+",middle"+middle+",end"+end+"]");
invokeAll(new CountNumbers(start, middle), new CountNumbers(middle, end));
}
}
public static void main(String[] args) {
ForkJoinTask<?> task = new CountNumbers(0,4);
ForkJoinPool pool = new ForkJoinPool();
Object result = pool.invoke(task);
}
}
Produces StackOverflowException:
rUser5@T59 ~/Desktop $ java CountNumbers
[start=0,middle2,end4]
[start=0,middle1,end2]
[start=0,middle0,end1]
[start=2,middle3,end4]
[start=1,middle1,end2]
[start=3,middle3,end4]
[start=0,middle0,end0]
[start=3,middle3,end3]
[start=0,middle0,end1]
...
For a parallel reduction with collect():
1. The stream must be parallel
2. Must have characteristic Collector.Characteristics.CONCURRENT
3. Must have characteristic Collector.Characteristics.UNORDERED
Collectors class includes 2 sets of these:
- Collectors.toConcurrentMap()
- Collectors.groupingByConcurrent
public static <T,K> Collector<T,?,ConcurrentMap<K,List<T>>> groupingByConcurrent(Function<? super T,? extends K> classifier)
Returns a concurrent Collector implementing a "group by" operation on input elements of type T, grouping elements according to a classification function.
This is a concurrent and unordered Collector.
// EXAMPLE
import java.time.LocalDate;
import java.time.Month;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
Map<Employee.Gender, Long> countByGender = Employee.persons().stream()
.collect(Collectors.groupingByConcurrent(Employee::getGender, Collectors.counting()));
System.out.println(countByGender);
}}
class Employee {
public static enum Gender {MALE, FEMALE}
private long id;
private String name;
private Gender gender;
private LocalDate dob;
private double income;
public Employee(long id, String name, Gender gender, LocalDate dob, double income) {
this.id = id;
this.name = name;
this.gender = gender;
this.dob = dob;
this.income = income;
}
public Gender getGender() {
return gender;
}
public static List<Employee> persons() {
Employee p1 = new Employee(1, "Jake", Gender.MALE, LocalDate.of(1971, Month.JANUARY, 1), 2343.0);
Employee p2 = new Employee(2, "Jack", Gender.MALE, LocalDate.of(1972, Month.JULY, 21), 7100.0);
Employee p3 = new Employee(3, "Jane", Gender.FEMALE, LocalDate.of(1973, Month.MAY, 29), 5455.0);
Employee p4 = new Employee(4, "Jode", Gender.MALE, LocalDate.of(1974, Month.OCTOBER, 16), 1800.0);
Employee p5 = new Employee(5, "Jeny", Gender.FEMALE, LocalDate.of(1975, Month.DECEMBER, 13), 1234.0);
Employee p6 = new Employee(6, "Jason", Gender.MALE, LocalDate.of(1976, Month.JUNE, 9), 3211.0);
List<Employee> persons = Arrays.asList(p1, p2, p3, p4, p5, p6);
return persons;
}
}
Collectors.groupingByConcurrent(String::length); returns a ConcurrentMap<T,List<T>>
//shorthand: Collectors.toConcurrentMap(keyMapper Function, valueMapper Function, mergeFunction BinaryOperator<U>)
Collectors.toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction) returns a ConcurrentMap<T,U>
BlockingDeque methods throw Checked InterruptedException and so make sure its handled or declared:
.offerFirst
.offerLast
.pollFirst
.pollLast
BlockingQueue methods also throw Checked InterruptedException and so make sure its handled or declared:
.offer
.poll
This code hangs and doesn't finish:
import java.util.concurrent.*;
import java.util.stream.*;
public class PrintConstants {
public static void main(String[] args) {
ExecutorService service = Executors.newScheduledThreadPool(10);
DoubleStream.of(2.3445,2.4434)
.forEach(c -> service.submit( () -> System.out.println(10*c), 10000, TimeUnit.MILLISECONDS));
service.execute(() -> System.out.println("Printed"), 10000, TimeUnit.MILLISECONDS);
// service.shutdown();
}
}
This code runs and throws an occasional divide/0 error:
//InvokeAllUsage.java
import java.util.concurrent.*;
import java.util.*;
public class InvokeAllUsage {
public InvokeAllUsage() {
System.out.println("creating service");
ExecutorService service = Executors.newFixedThreadPool(10);
List<MyCallable> futureList = new ArrayList<MyCallable>();
for ( int i=0; i<10; i++){
MyCallable myCallable = new MyCallable((long)i+1);
futureList.add(myCallable);
}
System.out.println("Start");
try{
List<Future<Long>> futures = service.invokeAll(futureList);
for(Future<Long> future : futures) {
try {
System.out.println("future.isDone = " + future.isDone());
System.out.println("future: call = "+future.get());
}
catch (CancellationException ce) {
ce.printStackTrace();
} catch (ExecutionException ee) {
ee.printStackTrace();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
} catch(Exception err) {
err.printStackTrace();
}
System.out.println("Completed");
service.shutdown();
}
public static void main(String args[]){
InvokeAllUsage demo = new InvokeAllUsage();
}
class MyCallable implements Callable<Long> {
Long id = 0L;
public MyCallable(Long val) {
this.id = val;
}
public Long call() {
if ( id % 5 == 0) {
id = id / 0;
}
return id;
}
}
}
a sychronized on a static method is the same as synchronized(ThisClass.class)
a sychronized on a instance method is the same as synchronized(this)
Concurency benefits resource heavy tasks rather than CPU intensive tasks because resource heavy task tend to get stuck and wait for things to finish.
Concurrency, by itself, doesn't guarantee which tasks finish first.
Concurrent tasks share the same memory
Concurrent tasks benefit performance even on a single CPU system.
CH.8
Be careful of questions that say "choose possible outcomes of the following code".
Lambda on a ExecutorService .execute should be a Runnable and not return a value.
Benefits of using .readPassword
More secure: Characters don't enter into reusable String interned pool because chars are stored in array
Arrays are thrown away from memory immediately after use
.readPassword is not more performant
.readPassword does not encrypt
.readPassword does not have a benefit of reading all character encodings any more than any other password entry methodology
When creating a new Console, its possible it can be null. If you start JVM from a background process, it wont have an active console.
Writer.append can thrown a IOException
c.writer gets a Writer instance from a Console instance
Serializable interface is not final
In serialization, certain exceptions can be thrown:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
Double forward slashes are not allowed when creating a new File
new File("c://book//java")
The data of some classes cannot be easily serialized , such as those managing threads or processes.
A class having a serializable inner class cannot be serialized because it has an implicit reference to the outer enclosing non-serializable class.
High level NIO Streams
BufferedOutputStream
DataOutputStream
ObjectOutputStream
PrintStream
BufferedInputStream
DataInputStream
LineNumberInputStream
ObjectInputStream
PushbackInputStream
OutputStreamWriter
PrintWriter
Low level NIO Streams
ByteArrayOutputStream
ByteArrayInputStream
FileInputStream
FileOutputStream
FileReader
FileWriter
Neither High nor Low Streams (abstract classes !!! used as references only to objects we instantiate )
InputStream
OutputStream
Reader
Writer
serialVersionUID, not by any other name. is optional
Read questions carefully. For example, I had a question with code showing a private fields, but the question stated that you should assume class has public getters/setters . So, I got the question wrong because I didn't read the question carefully enough.
Don't call .mark without checking .markSupported or else the call can throw a Runtime exception, giving you a indeterminate result.
CH.9 NIO.2
Paths does nothing else but has 2 overloaded .get methods!
No such thing as Path.get , use Paths.get
The Paths.get method is shorthand for the following code:
Path p4 = FileSystems.getDefault().getPath("/users/sally");
Path path = FileSystems.getDefault().getPath("logs", "access.log");
Paths.get(path.toUri()).equals( p.toAbsolutePath())
Path p1 = Paths.get("/tmp/foo");
Path p2 = Paths.get(args[0]);
Path p3 = Paths.get(URI.create("file:///Users/joe/FileTest.java"));
Files.isDirectory() works on symbolic links.
BasicFileAttributeView can set time on a file using .setTimes
BasicFileAttributeView can get a copy of BasicFileAttributes, which allows things like:
- get time values
- get size
- get boolean is folder/file
- .isSymbolicLink. .fileKey
For Files.createDirectory
UnsupportedOperationException - if the array contains an attribute that cannot be set atomically when creating the directory
FileAlreadyExistsException - if a directory could not otherwise be created because a file of that name already exists
IOException - if an I/O error occurs or the parent directory does not exist
SecurityException - In the case of the default provider, and a security manager is installed, the checkWrite method is invoked to check write access to the new directory.
Paths.get will throw
InvalidPathException - if the path string cannot be converted to a Path
NoSuchFileException is possible?
This appends to an existing file and so it wont create a new file:
BufferedWriter out = Files.newBufferedWriter(filePath, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
try {
final Path tmp = filePath.getParent();
if (tmp != null){ // null will be returned if the path has no parent
Files.createDirectories(tmp);
} ...
.resolve will append path without normalizing it.
Path base_2 = Paths.get("C:/tutorial/Java/JavaFX/Topic.txt");
Path path_2 = base_1.resolve("Demo.txt");
System.out.println(path_2.toString()); // prints C:/tutorial/Java/JavaFX/Demo.tx
Files.lines()
public static Stream<String> lines(Path path) throws IOException
Files.readAllLines()
public static List<String> readAllLines(Path path) throws IOException
Files.copy will also copy metadata by default
public static Path copy(Path source,
Path target,
CopyOption... options) throws IOException
REPLACE_EXISTING If the target file exists, then the target file is replaced if it is not a non-empty directory. If the target file exists and is a symbolic link, then the symbolic link itself, not the target of the link, is replaced.
COPY_ATTRIBUTES Attempts to copy the file attributes associated with this file to the target file. The exact file attributes that are copied is platform and file system dependent and therefore unspecified. Minimally, the last-modified-time is copied to the target file if supported by both the source and target file stores. Copying of file timestamps may result in precision loss.
NOFOLLOW_LINKS Symbolic links are not followed. If the file is a symbolic link, then the symbolic link itself, not the target of the link, is copied. It is implementation specific if file attributes can be copied to the new link. In other words, the COPY_ATTRIBUTES option may be ignored when copying a symbolic link.
UnsupportedOperationException - if the array contains a copy option that is not supported
FileAlreadyExistsException - if the target file exists but cannot be replaced because the REPLACE_EXISTING option is not specified (optional specific exception)
DirectoryNotEmptyException - the REPLACE_EXISTING option is specified but the file cannot be replaced because it is a non-empty directory (optional specific exception)
IOException - if an I/O error occurs
SecurityException - In the case of the default provider, and a security manager is installed, the checkRead method is invoked to check read access to the source file, the checkWrite is invoked
FileSystem class
public abstract Path getPath(String first, String... more)
NOTE: no such thing as Paths.getPath or Path.getPath
public void find_files(File root)
{
File[] files = root.listFiles();
for (File file : files) {
if (file.isFile()) {
...
} else if (file.isDirectory()) {
find_files(file);
}
}
}
Path start = Paths.get("");
int maxDepth = 5;
try (Stream<Path> stream = Files.find(start, maxDepth, (path, attr) -> String.valueOf(path).endsWith(".js"))) {
String joined = stream
.sorted()
.map(String::valueOf)
.collect(Collectors.joining("; "));
System.out.println("Found: " + joined);
}
Path path = Paths.get("");
Files.find(path, 0, (p,a) -> a.isSymbolicLink()).map(p -> p.toString())
.collect(Collectors.toList())
.stream()
.filter( x -> x.toString().endsWith(".txt"))
.forEach(System.out::println);
// Practice this also with read-only files
Path start = Paths.get("");
int maxDepth = 5;
try (Stream<Path> stream = Files.walk(start, maxDepth)) {
String joined = stream
.map(String::valueOf)
.filter(path -> path.endsWith(".js"))
.sorted()
.collect(Collectors.joining("; "));
System.out.println("walk(): " + joined);
}
try (Stream<String> stream = Files.lines(Paths.get("res/nashorn1.js"))) {
stream
.filter(line -> line.contains("print"))
.map(String::trim)
.forEach(System.out::println);
}
Path path = Paths.get("res/nashorn1.js");
try (BufferedReader reader = Files.newBufferedReader(path)) {
long countPrints = reader
.lines()
.filter(line -> line.contains("print"))
.count();
System.out.println(countPrints);
}
java.nio.Files also can get time attributes , not just from NIO2 BasicAttributesView
private boolean modifiedLaterThan(Path path, LocalDate pickedDate) {
try {
FileTime fileTime = Files.getLastModifiedTime(path);
Instant fileInstant = fileTime.toInstant();
Instant pickedInstant =
pickedDate.atStartOfDay(ZoneId.systemDefault()).toInstant();
return fileInstant.compareTo(pickedInstant) >= 0;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
No such thing as Files.files()
// UNDERSTAND .flatMap better and Stream.of(array)
import java.nio.file.*;
import java.util.stream.*;
import java.io.*;
public class Hello {
public static void main(String[] args) throws IOException {
Path path = Paths.get("Hello.csv");
Files.lines(path)
.flatMap(p -> Stream.of(p.split(",")))
.map(s -> s.toUpperCase())
.forEach(System.out::println);
}
}
Paths.get(".").normalize() returns current folder name only.
CH. 10 SQL
UNSORTED:
Singletons dont have public constructors.
Only a class without setter methods would be immutable.
In this example, Laptop extends Computer, and if both classes have 'void startup()' defined, both of these will call the method defined in Laptop.
Computer computer = new Laptop();
Laptop laptop = new Laptop();
computer.startup();
laptop.startup();
// REMEMBER!! Polymorphism says the method called is the one belonging to the actual object instantiated, not the reference.
For class instance members, then the value is associated with the class reference.
Virtual method invocation only works for methods, not instance variables!!!!!!
When overriding a method, access modifier cannot be "more specific/restrictive"
Don't confuse Singleton pattern with Immutable !
Singletons have private constructors.
Immutable has all instance members private and perhaps not required: to be final.
Immutable should set initial List values using new ArrayList<>(arg2) AND also on getter method, return a copy. We cannot allow access to the same List object reference outside the class or the class would effectively be mutable.
System.out.println( bus instanceof Collection) will fail at runtime, not compiletime since compiler does not definitively know that instances of Bus might extend Collection or not.
System.out.println(bus instanceof ArrayList) will fail to compile
class Building {}
class House extends Building {}
House q = (Building) h; // this is illegal, a Building cannot be stored in a House (superclass) reference
Two objects having the same hash code may or may not be equal.
If 2 objects satisfy .equals they must have the same .hashCode result.
The .getter on a Singleton must be static.
A singleton instance is not required to be final.
A singleton instance must have a private constructor, accessing instance only via a static public getter method.
Van implements Vehicle
Van[] vans = new Van[0]; // a legal declaration; i got this wrong!!
vans instanceof Vehicle[]; // valid
use instanceof NOT instanceOf !
Be careful on class method override questions. make sure signature matches!
Given:
class Building {}
class House extends Building {}
House h1 = (House) b1; // this compiles but fails at runtime! for the compiler, its ok to cast up a building to a house; i missed this. i know a building cant be stored in a House reference and so I thought the compiler would think you couldn't cast it
Encapsulation makes it easier to change instance variables since callers dont have direct access to them
Immutable class cannot allow methods to be overridden. Methods must be final and/or entire class must be final.
AN Object is required to return same value for repeated calls to .hashCode
Make SURE hashCode method never takes a parameter or else its not a real .hashCode method
Make sure .equals takes Object parameter, otherwise its not a real .equals override
the .equals method can have any implementation it wants if you dont define your own .hashCode implementation
So, public boolean .equals(Object o) { return true; } // would be ok in this case
With:
String table, chair = "metal"; only will initialize chair var.
An identifier name must begin with a letter, $, or _. Numbers are only permitted for subsequent characters.
Java automatically widens a type, allowing a float to be assigned to either a float or a double
"instance initializers" probably means "instance initializer blocks"
Local variables are not automatically initialized. Compiler will catch it though.
The finalize() method might/may not be called, such as if your program crashes. However, it is guaranteed to be called no more than once.
On longer questions, narrow down the answers and look for hints in sections of the code.
While it is bad practice to use the name of a class as your local variable name, this is legal.
int Integer = 0; // legal
Integer int = 0; // not legal
1_000_000_.0 is not a legal number
Local variables need to be initialized before they are used but if they aren't used it will still compile.
Connection is an interface for communicating with the database. Driver is tricky because you don’t write code that references it directly. However, you are still required to know it is a JDBC interface. DriverManager is used in JDBC code to get a Connection. However, it is a concrete class rather than an interface.
DriverManager.getConnection - call method on this concrete class
The Driver class is a interface without static methods, making Driver.getConnection(xx) incorrect. Option C is the answer because DriverManager is the class used in JDBC to get a Connection.
CallableStatement and PreparedStatement are interfaces that extend the Statement interface. You don’t need to know that for the exam. You do need to know that a database driver is required to provide the concrete implementation class of Statement rather than the JDK.
Scroll sensitive is a result set type parameter, and updatable is a concurrency mode. The result set type parameter is passed to createStatement() before the concurrency mode. If you request options that the database driver does not support, it downgrades to an option it does support rather than throwing an exception.
.createStatement( ResultSet TYPE, ResultSet CONCURRENT mode)
TODO: make sure i know these
There are two ResultSet concurrency modes: CONCUR_READ_ONLY and CONCUR_UPDATABLE. All database drivers support read-only result sets, but not all support updatable ones.
The execute() method is allowed to run any type of SQL statements. The executeUpdate() method is allowed to run any type of the SQL statement that returns a row count rather than a ResultSet. Both DELETE AND UPDATE SQL statements are allowed to be run with either execute() or executeUpdate(). They are not allowed to be run with executeQuery() because they do not return a ResultSet.
There are three "ResultSet type" options: TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, and TYPE_SCROLL_SENSITIVE.
rs.getString(0) , not rs.getString("0")
rs.getInt(0)
Since this code opens Statement using a try-with-resources, Statement gets closed automatically at the end of the block. Further, closing a Statement automatically closes a ResultSet created by it. Result set is not required to be in the try-with-resources parenthesis.
For Statement, You can turn off auto-commit mode, but it defaults to on.
The requirement to include a java.sql.Driver file in the META-INF directory was introduced in JDBC 4.0. Older drivers are not required to provide it. All drivers are required to implement the Connection interface.
You can call stmt over and over, its ok to re-use the rs instance like below...
rs = stmt.executeQuery
rs = stmt.executeQuery
etc.
When running a query on a Statement, Java closes any already open ResultSet objects!!
No such thing as rs.prev()
Practice quiz says this works when inserting into a 2 column table, but i dont believe it:
insert into table_name VALUES ("tst")
ResultSet get functions are 1-based!
rs.relative(-5) requires the ResultSet be scrollable
rs.relative(-x) cant move farther back than 0
Scrollable result set does not loop around.
BUT: rs.absolute(-1) always puts cursor at last record in result set
When creating the Statement, the code doesn’t specify a result set type. This means it defaults to TYPE_FORWARD_ONLY. The absolute() method can only be called on scrollable result sets. The code throws a SQLException
ResultSet options need to be supplied when creating the Statement object rather than when executing the query. Don't be tricked.
beforeFirst() has a void return type, NOT boolean
Class Design
----------------------
So all classes have at least one constructor.
Subclasses constructors may specify as the first thing they do which constructor in the superclass to invoke before executing the code in the subclass's constructor.
If the subclass constructor does not specify which superclass constructor to invoke then the compiler will automatically call the accessible no-args constructor in the superclass.
If the superclass has no no-arg constructor or it isn't accessible then not specifying the superclass constructor to be called (in the subclass constructor) is a compiler error so it must be specified.
If the parent class defines a 1 arg constructor without defining a no-arg, then there is not a no-arg constructor and you get a compiler error because of implicit super() in child class.
If a sub-class overrides a protected method, leaving the default as default package-private will fail to compile.
The access modifier must be the same or broader in the child method. Using a narrower/more-restrictive access modifier in the child class would not allow the code to compile.
Overridden methods must not throw any new or broader checked exceptions than the method in the superclass.
Overridden methods must throw a narrower exception than the method in superclass or throw nothing at all.
When overriding methods, make sure that the return type is covariant with what you override, but if you are overriding both a Interface: Integer play() method and a Abstract: Short play() method, it wont compile because the methods you are overriding are not covariant with themselves.
This is ok; this.material somehow refers to the static variable :
public class Book {
protected static String material = "papyrus";
public Book() {}
public Book(String material) {
this.material = material;
}
public static void main( String args[])
{
}
}
A reference to a class can be implicitly assigned to a superclass reference without an explicit class. Assigning a reference to a subclass, though, requires an explicit cast.
A reference to an interface requires an explicit cast to be assigned to a reference of any class, even one that implements the interface. An interface reference requires an explicit cast to be assigned to a class reference. An explicit cast is not required to assign a reference to a class that implements an interface to a reference of the interface.
interface Test {}
abstract class Book implements Test {
public String material = "papyrus";
public Book() {}
public Book(String material) {
this.material = material;
}
}
public class Novel extends Book {
public static void main( String args[])
{
Book b = new Novel();
System.out.println(b.material); // prints papyrus
Test t = (Test)b;
System.out.println(t.material); // fails to compile, no access for type
}
}
A class that defines an instance variable with the same name as a variable in the parent class is referred to as hiding a variable, while a class that defines a static method with the same signature as a static method in a parent class is referred to as hiding a method.
A static method cannot override a non-static method and vice versa.
In Java, only non-static, non-final, and non-private methods are considered virtual and capable of being overridden in a subclass.
You cant override a static method in a sub-class, you can only hide it.
If a class is abstract, so no object is instantiated, but there is no requirement that an abstract class cannot contain a runnable main() method.
Overridden methods must have covariant return types, which may not be exactly the same as the type in the parent class. Overridden methods therefore might not have the same return type.
If a parent class does not include a no-argument constructor (nor a default one inserted by the compiler), a child class must contain at least one constructor definition. If a parent class does not include a no-argument constructor, the child class must explicitly declare a constructor, since the compiler will not be able to insert the default no-argument constructor.
The primary motivation for adding default interface methods to Java was for backward compatibility. These methods allow developers to update older classes with a newer version of an interface without breaking functionality in the existing classes
The rule for overriding a method with exceptions is that the subclass cannot throw any new or broader checked exceptions. Since IOException is a superclass of EOFException, don't throw IOException in the overriding method.
Localization
-------------
Oracle defines a locale as a geographical, political, or cultural region.
Object[][] ListResourceBundle.getContents (NOT JavaResourceBundle!)
When both a language and country code are present, the language code comes first. The language code is in all lowercase letters and the country code is in all uppercase.
Java starts out by looking for a Java file with the most specific match, which is language and country code. Since this is happening at runtime, it is looking for the corresponding file with a .class extension. If this file was not found, Java would then look for a .properties file with the name
When extending ListResourceBundle, when you override the getContents method, then your multiple calls to rb.getObject only result in 1 initial call to .getContents .
A Locale can consist of a language only, It cannot consist of a country code without a language
en // ok
US // bad
US_en //bad
en_US // ok
A LocalDateTime property cannot be stored in a .properties file . We know we could translate a String into a LocalDateTime but that is not the same as storing the object literally , such as in a Java resource bundle.
At least one matching resource bundle must be available at the time of the call to getBundle() or else it will throw a MissingResourceException
Local.setDefault(new Locale("en", "US"));
ResourceBundle rb = new ResourceBundle.getBundle("colors");
rb.getString("colors")
// looks for Colors_en_US first
// looks for Colors_en second
// never searches for Colors_US
// looks for Colors last
No such thing as Locale.get
Properties class has a .put(Object) method
This means when you call props.getProperty("key") it will automagically cast the object back to a String before returning.
If you override getContents in your class, make sure you extend ListResourceBundle . You cannot create a ResourceBundle from such a class or it will throw and exception.
Local.KOREAN is ok if you pre-defined it.
rb.getString and rb.getObject are both ok
This is a legal array declaration and it works; its not obvious since it appears the .getObject call cant get a hold of the "test" key :
protected Object[][] getContents() {
return new Object[][] {{"test", new WhateverObject() }};
}
...
WhateverObject wo = (WhateverObject)rb.getObject("count");
A call to Resource.getBundle MUST include the full package qualified package + class name IF the resource is not in the same folder of the package that the program is in.
If you have Buggy_en.java and Buggy_en.properties and Buggy.java , the code will search and skip looking in Buggy_en.properties: it prefers the Java resource and then looks in the default resource after that.
Java does not allow looking in a properties file resource bundle once it has matched a Java class resource bundle.
If you have a ResourceBundle.getBundle("Colors", new Locale("zh", "CN));
if rb.getString("key") finds no match , Java will go on and search the default locale , then the language of the default Locale, and finally the default Local. Colors.properties or Colors.java would get searched very last.
ResourceBundle rb = new ResourceBundle is NOT VALID
Generic Wildcards
--------------------
An "in" variable is defined with an upper bounded wildcard, using the extends keyword.
An "out" variable is defined with a lower bounded wildcard, using the super keyword.
In the case where the "in" variable can be accessed using methods defined in the Object class, use an unbounded wildcard.
In the case where the code needs to access the variable as both an "in" and an "out" variable, do not use a wildcard.
List<EvenNumber> le = new ArrayList<>();
List<? extends NaturalNumber> ln = le;
ln.add(new NaturalNumber(35)); // compile-time error
List<B> lb = new ArrayList<>();
List<A> la = lb; // compile-time error
Although Integer is a subtype of Number, List<Integer> is not a subtype of List<Number> and, in fact, these two types are not related. The common parent of List<Number> and List<Integer> is List<?>.
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numList = intList; // OK. List<? extends Integer> is a subtype of List<? extends Number>
import java.util.*;
import java.io.*;
class Ai implements Comparable {
@Override
public int compareTo(Object o) {
return 0;
}
}
class Bi extends Ai {}
class Ci extends Bi {}
public class GenericWildcards
{
public static void main(String[] args)
{
List<?> list1 = new ArrayList<>();
List<? extends IOException> list2 = new ArrayList<IOException>();
List<? extends IOException> list3 = new ArrayList<FileNotFoundException>();
List<? super IOException> list4 = new ArrayList<Exception>();
//List<? extends Bi> list5 = new ArrayList<Ai>();
List<? super Bi> list6 = new ArrayList<Ai>();
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numList = intList; // OK. List<? extends Integer> is a subtype of List<? extends Number>
List<Integer> li = Arrays.asList(1, 2, 3);
List<Double> ld = Arrays.asList(10.10, 20.20, 30.30);
swapFirst(li, ld);
}
//void foo(List<?> i) {
// i.set(0, i.get(0)); //compile error
//}
// Helper method created so that the wildcard can be captured
// through type inference.
private <T> void fooHelper(List<T> l) {
l.set(0, l.get(0));
}
public <T> T method0(List<? extends T> list) {
return list.get(0);
}
public <Ci> Ci method1(List<? extends Ci> list) {
return list.get(0);
}
//public <Bi> <? extends Bi> method2(List<? extends Bi> list) {
// return list.get(0);
//}
public <Bi extends Comparable<Bi>> Ci method3(List<Ci> list) {
return list.get(0);
}
public <Bi extends Comparable<Bi>> Bi method4(List<Bi> list) {
return list.get(0);
}
public <Bi extends Comparable<Bi>> Ai method5(List<Ai> list) {
return list.get(0);
}
static void swapFirst(List<? extends Number> l1, List<? extends Number> l2) {
Number temp = l1.get(0);
//l1.set(0, l2.get(0)); // expected a CAP#1 extends Number,
// got a CAP#2 extends Number;
// same bound, but different types
// Error:(69, 33) java: incompatible types: java.lang.Number cannot be converted to capture#1 of ? extends java.lang.Number
//l2.set(0, temp); // expected a CAP#1 extends Number,
// got a Number
// Error:(72, 27) java: incompatible types: java.lang.Number cannot be converted to capture#2 of ? extends java.lang.Number
}
}
When declaring a class like so:
public class Node<T extends Comparable<T>> {
The compiler creates a class under the hood like this:
public class Node {
private Comparable data; // uses the first class of the bound
...
Pair<int, char> p = new Pair<>(8, 'a'); // compile-time error
Pair<Integer, Character> p = new Pair<>(8, 'a');
Note that the Java compiler autoboxes 8 to Integer.valueOf(8) and 'a' to Character('a'):
Pair<Integer, Character> p = new Pair<>(Integer.valueOf(8), new Character('a'));
You cannot create an instance of a type parameter. For example, the following code causes a compile-time error:
public static <E> void append(List<E> list) {
E elem = new E(); // compile-time error
list.add(elem);
}
As a workaround, you can create an object of a type parameter through reflection:
public static <E> void append(List<E> list, Class<E> cls) throws Exception {
E elem = cls.newInstance(); // OK
list.add(elem);
}
You can invoke the append method as follows:
List<String> ls = new ArrayList<>();
append(ls, String.class); // this is WHY I see this sometimes!!
Because the Java compiler erases all type parameters in generic code, you cannot verify which parameterized type for a generic type is being used at runtime:
public static <E> void rtti(List<E> list) {
if (list instanceof ArrayList<Integer>) { // compile-time error
// ...
}
}
The set of parameterized types passed to the rtti method is:
S = { ArrayList<Integer>, ArrayList<String> LinkedList<Character>, ... }
The runtime does not keep track of type parameters, so it cannot tell the difference between an ArrayList<Integer> and an ArrayList<String>. The most you can do is to use an unbounded wildcard to verify that the list is an ArrayList:
public static void rtti(List<?> list) {
if (list instanceof ArrayList<?>) { // OK; instanceof requires a reifiable type
// ...
}
}
Typically, you cannot cast to a parameterized type unless it is parameterized by unbounded wildcards. For example:
List<Integer> li = new ArrayList<>();
List<Number> ln = (List<Number>) li; // compile-time error
However, in some cases the compiler knows that a type parameter is always valid and allows the cast. For example:
List<String> l1 = ...;
ArrayList<String> l2 = (ArrayList<String>)l1; // OK
List<Integer>[] arrayOfLists = new List<Integer>[2]; // compile-time error
A generic class cannot extend the Throwable class directly or indirectly. For example, the following classes will not compile:
// Extends Throwable indirectly
class MathException<T> extends Exception { /* ... */ } // compile-time error
// Extends Throwable directly
class QueueFullException<T> extends Throwable { /* ... */ // compile-time error
You can, however, use a type parameter in a throws clause:
class Parser<T extends Exception> {
public void parse(File file) throws T { // OK
// ...
}
}
A class cannot have two overloaded methods that will have the same signature after type erasure.
public class Example {
public void print(Set<String> strSet) { }
public void print(Set<Integer> intSet) { }
}
EXCEPTIONS:
Example1:
import java.lang.Math;
public class HelloWorld
{
public static void main(String[] args)
{
new TestIt().doIt();
}
}
class TestIt {
public int doIt() // no throws declare needed because we use a local try-block
{
int top = 10;
int divisor = 0;
int result;
try{
result = top/divisor;
}
catch (Exception e)
{
//throw e; // shows ArithmeticException: / by zero
throw new RuntimeException(e); // shows 'ArithmeticException: / by zero' caused-by withing a wrapped RuntimeException
//throw new RuntimeException("Test", e); // shows 'Test' caused-by withing a wrapped RuntimeException (hides actual error!!)
//return; // silent; throws away exception; does not re-throw
}
return result;
}
}
Example2:
import java.lang.Math;
public class HelloWorld
{
public static void main(String[] args)
{
try{
new TestIt().doIt();
}
catch (Exception e)
{
//throw e; // shows ArithmeticException: / by zero
throw new RuntimeException(e); // shows 'ArithmeticException: / by zero' caused-by withing a wrapped RuntimeException
//throw new RuntimeException("Test", e); // shows 'Test' caused-by withing a wrapped RuntimeException (hides actual error!!)
//return; // silent; throws away exception; does not re-throw
}
}
}
class TestIt {
public int doIt() throws Exception
{
int top = 10;
int divisor = 0;
return top/divisor;
}
}
Example 3:
public class Java7ExceptionRethrow {
public static void main(String[] args) throws Exception
{
try {
rethrowIt("abc");
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
static void rethrowIt(String s) throws FirstException, SecondException, ThirdException
{
try {
if (s.equals("First"))
throw new FirstException("First");
else if (s.equals("Second"))
throw new SecondException("Second");
else
throw new ThirdException("Third");
} catch (Exception e) {
throw e;
}
}
static class FirstException extends Exception {
public FirstException(String msg) {
super(msg);
}
}
static class SecondException extends Exception {
public SecondException(String msg) {
super(msg);
}
}
static class ThirdException extends Exception {
public ThirdException(String msg) {
super(msg);
}
}
}
import java.util.*;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "a", "a", "a"));
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
String s = iter.next();
if (s.equals("a")) {
iter.remove();
System.out.println(list.size()); // size drops each time without concurrentmodification error
}
}
// example that doesnt work
ArrayList<String> list2 = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
for (String s : list2) {
if (s.equals("a"))
list2.remove(s); //java.util.ConcurrentModificationException
}
}
}
WONT COMPILE:
import java.util.*;
public class Main{
public static void add(List list, Object o){
list.add(o); //warning: [unchecked] unchecked call to add(E) as a member of the raw type List
}
public static void main(String[] args){
List<String> list = new ArrayList<String>();
add(list, 10);
String s = list.get(0);
}
}
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
public class RecursiveTaskDemo
{
public static void main(String[] args) {
FibonacciCal fibonacciCal = new FibonacciCal(12);
ForkJoinPool pool = new ForkJoinPool();
int i = pool.invoke(fibonacciCal);
System.out.println(i);
}
}
// RecursiveTask returns a value, unlike its cousin
class FibonacciCal extends RecursiveTask<Integer>
{
private static final long serialVersionUID = 1L;
final int num;
FibonacciCal(int num) { this.num = num; }
@Override
protected Integer compute() {
if (num <= 1){
return num;
}
FibonacciCal fcal1 = new FibonacciCal(num - 1);
fcal1.fork();
FibonacciCal fcal2 = new FibonacciCal(num - 2);
return fcal2.compute() + fcal1.join();
}
}
The Instant class does not work with human units of time, such as years, months, or days. If you want to perform calculations in those units, you can convert an Instant to another class, such as LocalDateTime or ZonedDateTime, by binding the Instant with a time zone.
Example of class object as type literal:
public static <T> T read(Class<T> theClass, String sql) throws IllegalAccessException, InstantiationException {
//execute SQL.
T o = theClass.newInstance();
//set properties via reflection.
return o;
}
Here is how you would call the read() method:
Driver employee = read(Driver.class, "select * from drivers where id=1");
Vehicle vehicle = read(Vehicle.class, "select * from vehicles where id=1");
When you know that the list is typed to either A, or a superclass of A, it is safe to insert instances of A or subclasses of A (e.g. B or C) into the list. Here is an example:
public static void insertElements(List<? super A> list){
list.add(new A());
list.add(new B());
list.add(new C());
}
All of the elements inserted here are either A instances, or instances of A's superclass. Since both B and C extend A, if A had a superclass, B and C would also be instances of that superclass.
Given:
public static <T> T writeAll(Collection<? extends T> coll, Sink<T> snk) {
T last;
for (T t : coll) {
last = t;
snk.flush(last);
}
return last;
}
...
Sink<Object> s;
Collection<String> cs;
String str = writeAll(cs, s);
// without ? extends T, this would not work.
// also notice return type is wrong unless we use Sink<? super T> snk
public static <T extends Comparable<? super T>> T max(Collection<T> coll)
// here, <T extends Comparable<? super T>> speaks/defines/restricts the argument coll
Set<?> s = Collections.unmodifiableSet(unknownSet); // this is ok
public static <T extends Object & Comparable<? super T>> T max(Collection<T> coll) // this is ok
.mapping Collector example:
Map<BigDecimal, Set<String>> result =
items.stream().collect(
Collectors.groupingBy(Item::getPrice,
Collectors.mapping(Item::getName, Collectors.toSet())
)
);
import java.util.*;
import java.util.stream.*;
import java.util.function.*;
public class Hello {
public static void main(String[] args) {
List<String> items =
Arrays.asList("apple", "apple", "banana",
"apple", "orange", "banana", "papaya");
Map<String, Long> result =
items.stream().collect(
Collectors.groupingBy(
Function.identity(), Collectors.counting()
)
);
Map<String, Long> finalMap = new LinkedHashMap<>();
result.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue()
.reversed()).forEachOrdered(e -> finalMap.put(e.getKey(), e.getValue()));
System.out.println(finalMap); // apple=3, banana=2, papaya=1, orange=1
}
}
// static <K,V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue()
// Returns a comparator that compares Map.Entry in natural order on value.
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.Setter;
public class Java8Examples3 {
public static void main(String[] args) {
List<Item> items = Arrays.asList(
new Item("apple", 10, new BigDecimal("9.99")),
new Item("banana", 20, new BigDecimal("19.99")),
new Item("orang", 10, new BigDecimal("29.99")),
new Item("watermelon", 10, new BigDecimal("29.99")),
new Item("papaya", 20, new BigDecimal("9.99")),
new Item("apple", 10, new BigDecimal("9.99")),
new Item("banana", 10, new BigDecimal("19.99")),
new Item("apple", 20, new BigDecimal("9.99"))
);
Map<String, Long> counting = items.stream().collect(
Collectors.groupingBy(Item::getName, Collectors.counting()));
System.out.println(counting);
Map<String, Integer> sum = items.stream().collect(
Collectors.groupingBy(Item::getName, Collectors.summingInt(Item::getQty)));
System.out.println(sum);
}
}
class Item {
@Getter @Setter private String name;
@Getter @Setter private int qty;
@Getter @Setter private BigDecimal price;
}
Collectors.toMap(p -> p.getLast(), Function.identity())
or, more concisely, you can use a method reference using ::
Collectors.toMap(Person::getLast, Function.identity())
and inst
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment