- forEach method in java.lang.Iterable interface
Java 8 has introduced forEach method in java.lang.Iterable interface so that while writing code we focus on business logic. The forEach method takes java.util.function.Consumer object as an argument, so it helps in having our business logic at a separate location that we can reuse.
- Interfaces with default and static methods
From Java 8, interfaces are enhanced to have a method with implementation. We can use default and static keyword to create interfaces with method implementation
- @FunctionalInterface annotation. Functional interfaces are a new concept introduced in Java 8. An interface with exactly one abstract method becomes a Functional Interface. We don’t need to use @FunctionalInterface annotation to mark an interface as a Functional Interface.
@FunctionalInterface annotation is a facility to avoid the accidental addition of abstract methods in the functional interfaces. You can think of it like @Override annotation and it’s best practice to use it. java.lang.Runnable with a single abstract method run() is a great example of a functional interface.
Anonymous Class Implementation
Runnable r = new Runnable() { @Override public void run() { System.out.println("My Runnable"); } };
Lambda Expression Implementation
Runnable r1 = () - > { System.out.println("My Runnable"); };
If you have single statement in method implementation anonymous class can be instantiated using lambda expression as below
lambda expressions ImplementationInterface1 i1 = (s) -> System.out.println(s); i1.method1("abc");
- New java.util.stream has been added in Java 8 to perform filter/map/reduce like operations with the collection. Stream API will allow sequential as well as parallel execution.
public static void main(String[] args) { List < Integer > myList = new ArrayList < > (); for (int i = 0; i < 100; i++) myList.add(i); //sequential stream Stream < Integer > sequentialStream = myList.stream(); //parallel stream Stream < Integer > parallelStream = myList.parallelStream(); //using lambda with Stream API, filter example Stream < Integer > highNums = parallelStream.filter(p - > p > 90); //using lambda in forEach highNums.forEach(p - > System.out.println("High Nums parallel=" + p)); Stream < Integer > highNumsSeq = sequentialStream.filter(p - > p > 90); highNumsSeq.forEach(p - > System.out.println("High Nums sequential=" + p)); }
parallel processing values are not in order, so parallel processing will be very helpful while working with huge collections.
- IO improvements known to me are:
Files.list(Path dir) that returns a lazily populated Stream, the elements of which are the entries in the directory.
Files.lines(Path path) that reads all lines from a file as a Stream.
Files.find() that returns a Stream that is lazily populated with Path by searching for files in a file tree rooted at a given starting file.
BufferedReader.lines() that return a Stream, the elements of which are lines read from this BufferedReader. - Java Time API packages, I can sense that they will be very easy to use. It has some sub-packages java.time.format that provides classes to print and parse dates and times and java.time.zone provides support for time zones and their rules.
myList.forEach(new Consumer < Integer > () { public void accept(Integer t) { System.out.println("forEach anonymous class Value::" + t); } }); //traversing with Consumer interface implementation MyConsumer action = new MyConsumer(); myList.forEach(action);
Consumer implementation that can be reused
class MyConsumer implements Consumer<Integer>{ public void accept(Integer t) { System.out.println("Consumer impl Value::"+t); } }
We know that Java doesn’t provide multiple inheritance in Classes because it leads to Diamond Problem. So how it will be handled with interfaces now since interfaces are now similar to abstract classes. Compiler will throw an exception in this scenario and we will have to provide implementation logic in the class implementing the interfaces.
@FunctionalInterface public interface Interface1 { void method1(String str); default void log(String str) { System.out.println("I1 logging::" + str); } static void print(String str) { System.out.println("Printing " + str); } }
interfaces are not allowed to have Object default methods.