1. Interfaces can have method definitions

a. abstract – just the declaration
b. default – has definition
c. static – has definition

2. Iterable interface has a default implementation of forEach method

List<Integer> list = new ArrayList<Integer>();
    for (int i = 0; i < 10; i++) {
        list.add(i);
    }
    list.forEach(new Consumer<Integer>() {    
        @Override
        public void accept(Integer arg0) {
            System.out.println(arg0); 
        }
    });

3. Functional Interfaces & Lambda expressions

An interface with exactly one abstract method becomes a functional interface.

@FunctionalInterface
Interfaceinterface MyTimbuktuInterface {
    public void justOneAbstractMethod(int ticketNumber);
}

// I have a lot to say
MyTimbuktuInterface timbuktu= (int ticketNumber) -> {
    System.out.println("This Lambda expression took me to Timbuktu.");
    System.out.println("I want to keep talking");
};

// I don't speak much, just one line
MyTimbuktuInterface timbuktu= (int ticketNumber) ->  System.out.println("This Lambda expression took me to Timbuktu.");

4. Java streams API

These are added to perform filter/map/reduce like operations with the collections.

List<Integer> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
    list.add(i);
}
Stream<Integer> stream1 = list.stream();
Stream<Integer> parallelStream1 = list.parallelStream();
Stream<Integer> filteredNums = stream1.filter(p -> p > 50);
filteredNums.forEach(p -> System.out.println(p));
Stream<Integer> filteredParallelStrm = parallelStream1.filter(p -> p > 50);
filteredParallelStrm.forEach(p -> System.out.println("parallel = " + p));

5) Collections

HashMap’s bucket is a red-black tree. Earlier it used to be a LinkedList.