What Is Java 8? Features Review

java 8 changes banner

Termed as one of the most comprehensive and pragmatic Java releases, Java 8 has been a stepping stone in shaping the course of programming languages in the right direction. But what is Java 8 exactly? Well, it is a revolutionary update to the Java program in terms of its language and libraries. The suite was released on the 18th March 2014, and it’s about time we had a detailed review on the Java 8 ArrayList API. We’re going to have a look at its features and functions, as well as Java expression tree.

If you haven’t gotten Java 8 yet, you can follow the steps below first:

  • Proceed by downloading the application file JDK8 and install it in your operating system. The JDK application is important because it is the interface that you will use to write programs, compile them, and further run them on Java.
  • You can then download the latest version of Eclipse IDE that is essential in providing extensive support for Java 8.

List of Java 8 Key Features

So without further ado, here are the most impressive Java 8 key features we found with examples demonstrating their effectiveness. You can also take a look at the top features of Java 9.

1. forEach Method

This method is utilized in the Iterable interface. It happens that whenever we require moving through a collection, we will have to create an Iterator that serves to iterate over. We find that whenever a business logic is present in a loop for every element of the Collection, then the concurrentModificationException error might appear if the iterator is not utilized in the right way. In fact, Java 8 changes have improved the forEach method in the following interfaces:

java.lang.Iterable so that one can focus on the business logic aspect of the code only while they write it.

java.util.function.Consumer is taken as an argument by the forEach method in order to assist in separating our business logic to another location for future use. For example:

EXAMPLE 1

package com.journaldev.java8.foreach;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import java.lang.Integer;
public class Java8ForEachExample {
public static void main(String[] args) {
//creating sample Collection
List<Integer> myList = new ArrayList<Integer>();
. for(int i=0; i<10; i++) myList.add(i);
//traversing using Iterator
Iterator<Integer> it = myList.iterator();
while(it.hasNext()){
Integer i = it.next();
System.out.println("Iterator Value::"+i);
}
//traversing through forEach method of Iterable with anonymous class
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
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);
}
}

As shown above, the forEach method assists in separating the business logic from the iteration logic for a cleaner and more fluid code.

2. Default and Static Uses in Interfaces

The cool thing about Java 8 interfaces is that they can be enhanced to have both the method together with implementation. This is through the use of the default and static options that will create an interface having method implementation. Let’s have a look at the example below:

EXAMPLE 2

default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}

Due to the Diamond Problem error, Java is unable to provide the option of multiple inheritance in classes. So how will it be able to deal with interfaces which are similar to having abstract classes? Well, we can find the solution in the compiler. It will give an exception to the above-mentioned case scenario; but as users, we will be mandated to give the implementation logic for the classes. This is shown below:

EXAMPLE 3

package com.journaldev.java8.defaultmethod;
@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);
}
//trying to override Object method gives compile time error as
//"A default method cannot override a method from java.lang.Object"
//default String toString(){
// return "i1";
// }
}

EXAMPLE 4

package com.journaldev.java8.defaultmethod;
@FunctionalInterface
public interface Interface2 {
void method2();
default void log(String str){
System.out.println("I2 logging::"+str);
}
}

You can see that both interfaces have a similar method log() each with an implementation logic.

EXAMPLE 5

package com.journaldev.java8.defaultmethod;
public class MyClass implements Interface1, Interface2 {
@Override
public void method2() {
}
@Override
public void method1(String str) {
}
//MyClass won't compile without having it's own log() implementation
@Override
public void log(String str){
System.out.println("MyClass logging::"+str);
Interface1.print("abc");
}
}

As can be observed, the Interface1 utilizes the static method implementation that was initially used in MyClass.log() implementation method.

3. Lambda Expressions and Functional Interfaces

Functional interfacing is a relatively new concept that has been introduced in Java 8. It is an interface with exactly one singular abstract method that then becomes a functional interface.

A great benefit of using functional interfacing is that you can easily use lambda expressions to create them instantly. Here is an example:

Runnable r1 = () -> {
System.out.println("My Runnable");
};

In the case that you have a single statement, you can shorten the above code as follows:

Interface1 i1 = (s) -> System.out.println(s);
i1.method1("abc");

Lambda expressions are therefore utilized to create classes related to functional interfaces in a much easier fashion.

Discover the niceties of ternary operator in Java!

4. Java Stream API Which Is Used for Large Data Collections and Operations

Java.util.stream is a new add-on that enables one to execute reduce, filter or map operations using the collection. Stream API is one of the best features because it allows you to work efficiently with Collections; especially dealing with large data. For example, it allows you to undertake parallel as well as sequential execution.

There have been further extensions of stream(), parallelStream() defaults as shown below:

EXAMPLE 6

package com.journaldev.java8.stream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class StreamExample {
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));
}
}

When you run the above code, you will get the output shown below:

High Nums parallel=91
High Nums parallel=96
High Nums parallel=93
High Nums parallel=98
High Nums parallel=94
High Nums parallel=95
High Nums parallel=97
High Nums parallel=92
High Nums parallel=99
High Nums sequential=91
High Nums sequential=92
High Nums sequential=93
High Nums sequential=94
High Nums sequential=95
High Nums sequential=96
High Nums sequential=97
High Nums sequential=98
High Nums sequential=99

The first thing that you will notice with your output is that there is no order in the values of the parallel processing. Therefore, parallel processing is beneficial whenever you’re working with a large collection of data.

what is java 8 meme

5. Java Time API

It was always difficult to work with the aspect of date and time in initial releases of Java. However, Java 8 has the java.time feature that will harmonize the activity of coding in real time. It has further sub-packages such as the java.time.format, java.time.zone, and the DateTimeFormatter, ArrayList API Java 8 all available for use.

On a final note, Java 8 has certainly brought with it some awesome features that make the coding process much simpler. And to add on that, we will assist you in mastering all the essential features that this amazing language offers.

Still not sure what is Java 8? Get in touch with us and improve your Java 8 knowledge!