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

Difference between foreach and enhanced for loop can be referenced here 

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. Lamba Expressions : 

A lambda expression is an anonymous function. A function that doesn’t have a name and doesn’t belong to any class. The concept of lambda expression was first introduced in LISP programming language.

To create a lambda expression, we specify input parameters (if there are any) on the left side of the lambda operator ->, and place the expression or block of statements on the right side of lambda operator. For example, the lambda expression (x, y) -> x + y specifies that lambda expression takes two arguments x and y and returns the sum of these.

//Syntax of lambda expression
(parameter_list) -> {function_body}

A method (or function) in Java has these main parts: Name, Parameter list,  Body, return type where as Lambda expression only has body and parameter list.

Where to use the Lambdas in Java

To use lambda expression, you need to either create your own functional interface or use the pre defined functional interface provided by Java. An interface with only single abstract method is called functional interface(or Single Abstract method interface), for example: Runnable, callable, ActionListener etc.

Click here for few examples with Lambdas.

5. Method References : 

Method reference is a shorthand notation of a lambda expression to call a method. For example:
If your lambda expression is like this:

str -> System.out.println(str)

then you can replace it with a method reference like this:

System.out::println

The :: operator is used in method reference to separate the class or object from the method name.

Definition from Oracle docs : You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it’s often clearer to refer to the existing method by name. Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.

Four types of method references

1. Method reference to an instance method of an object – object::instanceMethod
2. Method reference to a static method of a class – Class::staticMethod
3. Method reference to an instance method of an arbitrary object of a particular type – Class::instanceMethod
4. Method reference to a constructor – Class::new

Click here for examples.

6. Java streams API

Stream API which is another new feature of java 8. All the classes and interfaces of this API is in the java.util.stream package. By using streams we can perform various aggregate operations on the data returned from collections, arrays, Input/Output operations.

How to work with Stream in Java

As we have seen in the above example, the working of stream can be explained in three stages:
1. Create a stream
2. Perform intermediate operations on the initial stream to transform it into another stream and so on on further intermediate operations. In the above example, the filter() operation is intermediate operation, there can be more than one intermediate operations.
3. Perform terminal operation on the final stream to get the result. In the above example, the count() operation is terminal operation.

Stream Features :
1. Stream does not store the elements. it simply performs the aggregate operations(such as filter() and count() that we have seen in the above example) to get the desired stream of data.
2. The aggregate operations that we perform on the collection, array or any other data source do not change the data of the source, they simply return a new stream

Ex:
Iterating and displaying selected integers:
import java.util.stream.*;
public class StreamExample{
public static void main(String[] args){
Stream.iterate(1, count->count+1)
.filter(number->number%3==0)
.limit(6)
.forEach(System.out::println);
}
}
Output: 3,6,9,12,15,18

Click Here for examples

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

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

7) Collections

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