Below are the Java 8 new features and please open any java ide online or offline to write the code for practical understanding of the concept.
1. Java Lambda Expressions.
2. Java Method References.
3. Java Functional Interfaces
4. Java 8 Stream
5. Java Stream filter
6. Java encoder
7. Java default Method
8. Java forEach Method
9. Collectors
10. String joiner
11. Java Optional class
12. Java Nashorn
13. Java parallel sorting
14. Java type Inference
15. Method Parameter reflection
16. Java type annotation
17. Java jdbc improvement
1. Java Lambda Expressions
Java Lambda Expressions.
i. Lambda expression is a new and important feature of Java which was included in Java SE 8.
ii. It provides a clear and concise way to represent one method interface using an expression.
iii. It is very useful in collection library. It helps to iterate, filter and extract data from collection.
iv. Before lambda expression, anonymous inner class was the only option to implement the method.
In other words, we can say it is a replacement of java inner anonymous class.
Note: if you don’t know how to write anonymous inner class and its implementation please take help from below code:
| interface Drawable{ public void draw(); } public class AnoonymousClass{ public static void main(String[] args) { int width=10; //Drawable implementation using anonymous class Drawable d = new Drawable(){ public void draw(){System.out.println(“Drawing “+width);} }; d.draw(); } } Output:Drawing 10 |
v. Java lambda expression is treated as a function, so compiler does not create .class file
Functional Interface
i. Lambda expression provides implementation of functional interface.
ii. An interface which has only one abstract method is called functional interface.
iii. Java provides an annotation @FunctionalInterface, which is used to declare an interface as functional interface.
Why use Lambda Expression
i. To provide the implementation of Functional interface.
ii. Less coding.
Java Lambda Expression Syntax:
| (argument-list) -> {body} |
Java lambda expression is consisted of three components:
Ø Argument-list: It can be empty or non-empty as well.
Ø Arrow-token: It is used to link arguments-list and body of expression.
Ø Body: It contains expressions and statements for lambda expression.
v Java Example without Lambda Expression:
| interface Drawable{ public void draw(); } public class LambdaExpressionExample { public static void main(String[] args) { int width=10; //without lambda, Drawable implementation using anonymous class Drawable d=new Drawable(){ public void draw(){System.out.println(“Drawing “+width);} }; d.draw(); } } Output:Drawing 10 |
v Java Example with Lambda Expression:
Now, we are implementing the above example with the help of lambda expression.@FunctionalInterface //It is optional interface Drawable{ public void draw(); } public class LambdaExpressionExample { public static void main(String[] args) { int width=10; //with lambda Drawable d2=()->{ System.out.println (“Drawing “+width); }; d2.draw(); } } Output:Drawing 10 |
v Java Lambda Expression Example: Single Parameter:
| interface Sayable{ public String say(String name); } public class LambdaExpressionExample{ public static void main(String[] args) { // Lambda expression with single parameter. Sayable s1=(name)->{ return “Hello, “+name; }; System.out.println (s1.say(“Parmeshwar”)); // You can omit function parentheses Sayable s2= name ->{ return “Hello, “+name; }; System.out.println (s2.say(“Parmeshwar “)); } } Output:Hello, ParmeshwarHello, Parmeshwar |
v Java Lambda Expression Example: Multiple Parameters:
interface Addable{ int add(int a,int b); } public class LambdaExpressionExample{ public static void main(String[] args) { // Multiple parameters in lambda expression without return keyword Addable ad1= (a , b)->(a+b); System.out.println(ad1.add(10,20)); // Multiple parameters with data type in lambda expression Addable ad2= (int a , int b)->{ return (a+b); }; System.out.println(ad2.add(100,200)); } } Output:30300 |
v Java Lambda Expression Example: forEach Loop:
import java.util.*; public class LambdaExpressionExample{ public static void main(String[] args) { List<String> list=new ArrayList<String>(); list.add (“ankit”); list.add (“mayank”); list.add(“irfan”); list.add(“jai”); list.forEach( (n)->System.out.println (n) OR (n) -> { System.out.println (n) ;} ); } } Output: ankitmayankirfan Jai |
v Java Lambda Expression Example: Multiple Statements:
@FunctionalInterface interface Sayable{ String say(String message); } public class LambdaExpressionExample{ public static void main(String[] args) { // You can pass multiple statements in lambda expression Sayable person = (message)-> { String str1 = “I would like to say, “; String str2 = str1 + message; return str2; }; System.out.println(person.say(“time is precious.”)); } Output: I would like to say, time is precious. |
v Java Lambda Expression Example: Creating Thread:
You can use lambda expression to run thread. In the following example, we are implementing run method by using lambda expression.
| public class LambdaExpressionExample{ public static void main(String[] args) { //Thread Example without lambda Runnable r1=new Runnable(){ public void run(){ System.out.println(“Thread1 is running…”); } }; Thread t1=new Thread(r1); t1.start(); //Thread Example with lambda Runnable r2=()->{ System.out.println(“Thread2 is running…”); }; Thread t2=new Thread(r2); t2.start(); } } Output:Thread1 is running…Thread2 is running… |
v Java Lambda Expression Java lambda expression can be used in the collection framework:
It provides efficient and concise way to iterate, filter and fetch data. Following are some lambda and collection examples provided:
Java Lambda Expression Example: Comparator
| import java.util.ArrayList; import java.util.Collections; import java.util.List; class Product{ int id; String name; float price; public Product(int id, String name, float price) { super(); this.id = id; this.name = name; this.price = price; } } public class LambdaExpressionExample{ public static void main(String[] args) { List<Product> list=new ArrayList<Product>(); //Adding Products list.add(new Product(1,”HP Laptop”,25000f)); list.add(new Product(3,”Keyboard”,300f)); list.add(new Product(2,”Dell Mouse”,150f)); System.out.println(“Sorting on the basis of name…”); // implementing lambda expression Collections.sort(list,(p1,p2)->{ return p1.name.compareTo(p2.name); }); OR list.sort( (Product p1 , Product p2)->p1.getId()-p2.getId()); /* for(Product p:list){ System.out.println(p.id+” “+p.name+” “+p.price); } } } }Output:Sorting on the basis of name…2 Dell Mouse 150.01 HP Laptop 25000.03 Keyboard 300.0 |
vJava Lambda Expression Example: Filter Collection Data:
| import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; class Product{ int id; String name; float price; public Product(int id, String name, float price) { super(); this.id = id; this.name = name; this.price = price; } } public class LambdaExpressionExample{ public static void main(String[] args) { List<Product> list=new ArrayList<Product>(); list.add(new Product(1,”Samsung A5″,17000f)); list.add(new Product(3,”Iphone 6S”,65000f)); list.add(new Product(2,”Sony Xperia”,25000f)); list.add(new Product(4,”Nokia Lumia”,15000f)); list.add(new Product (5,”Redmi4 “,26000f)); list.add(new Product(6,”Lenevo Vibe”,19000f)); // using lambda to filter data Stream<Product> filtered_data = list.stream().filter(p -> p.price > 20000); // using lambda to iterate through collection filtered_data.forEach( product -> System.out.println(product.name+”: “+product.price) ); } } Output:Iphone 6S: 65000.0Sony Xperia: 25000.0Redmi4 : 26000.0 |
2. Java Method References
Ø Java provides a new feature called method reference in Java 8.
Ø Method reference is used to refer method of functional interface.
Ø It is compact and easy form of lambda expression.
Ø Each time when you are using lambda expression to just referring a method,
Ø You can replace your lambda expression with method reference.
Types of Method References
There are four types of method references:
1. Reference to a static method.
2. Reference to an instance method of a particular object.
3. Reference to an instance method of an arbitrary object of a particular type.
4. Reference to a constructor.
1.Reference to a Static Method
a. You can refer to static method defined in the class.
b. Following is the syntax and example which describe the process of referring static method in Java.
Syntax:
ContainingClass::staticMethodName
Example 1
In the following example, we have defined a functional interface and referring a static method to its functional method say().
| interface Sayable{ void say(); } public class MethodReference { public static void saySomething(){ System.out.println(“Hello, this is static method.”); } public static void main(String[] args) { // Referring static method Sayable sayable = MethodReference::saySomething; // Calling interface method sayable.say(); } } Output:Hello, this is static method. |
Example 2
You can also use predefined functional interface to refer methods. In the following example, we are using BiFunction interface and using it’s apply() method.
| import java.util.function.BiFunction; class Arithmetic{ public static int add(int a, int b){ return a+b; } } public class StaticMethodReference { public static void main(String[] args) { BiFunction<Integer, Integer, Integer>adder = Arithmetic::add; int result = adder.apply(10, 20); System.out.println(result); } } |
Example 3
You can also override static methods by referring methods. In the following example, we have defined and overloaded three add methods.
| import java.util.function.BiFunction; class Arithmetic{ public static int add(inta, intb){ return a+b; } public static float add(inta, floatb){ return a+b; } public static float add(floata, floatb){ return a+b; } } public class StaticMethodReference { public static void main(String[] args) { BiFunction<Integer, Integer, Integer>adder1 = Arithmetic::add; BiFunction<Integer, Float, Float>adder2 = Arithmetic::add; BiFunction<Float, Float, Float>adder3 = Arithmetic::add; intresult1 = adder1.apply(10, 20); floatresult2 = adder2.apply(10, 20.0f); floatresult3 = adder3.apply(10.0f, 20.0f); System.out.println(result1); System.out.println(result2); System.out.println(result3); } } Output:3030.030.0 |
2. Reference to an Instance Method
i. Like static methods, you can refer instance methods also. In the following example, we are describing the process of referring the instance method.
Syntax:
containingObject::instanceMethodName
Example 1
In the following example, we are referring non-static methods. You can refer methods by class object and anonymous object.
| interface Sayable{ void say(); } public class MethodReference { public void saySomething(){ System.out.println(“Hello, this is non-static method.”); } public static void main(String[] args) { MethodReference methodReference = new MethodReference(); // Creating object // Referring non-static method using reference Sayable sayable = methodReference::saySomething; // Calling interface method sayable.say(); // referring non-static method using anonymous object Sayable sayable2 = new MethodReference()::saySomething; // You can use anonymous object also // Calling interface method sayable2.say(); } } Output:Hello, this is non-static method. Hello, this is non-static method. |
Example 2
In the following example, we are referring instance (non-static) method. Runnable interface contains only one abstract method. So, we can use it as functional interface.
| public class InstanceMethodReference { public void printnMsg(){ System.out.println(“Hello, this is instance method”); } public static void main(String[] args) { Thread t2=new Thread(new InstanceMethodReference()::printnMsg); t2.start(); } } Output:Hello, this is instance method |
Example 3
In the following example, we are using BiFunction interface. It is a predefined interface and contains a functional method apply().
Here, we are referring add method to apply method.
| import java.util.function.BiFunction; class Arithmetic{ public int add(inta, intb){ return a+b; } } public class InstanceMethodReference { public static void main(String[] args) { BiFunction<Integer, Integer, Integer>adder = new Arithmetic()::add; int result = adder.apply(10, 20); System.out.println(result); } } OUTPUT: 30 |
3) Reference to a Constructor
You can refer a constructor by using the new keyword. Here, we are referring constructor with the help of functional interface.
Syntax:
ClassName::new
Example:
| interface Messageable{ Message getMessage(String msg); } class Message{ public Message(String msg){ System.out.print(msg); } } public class ConstructorReference { public static void main(String[] args) { Messageable hello = Message::new; hello.getMessage(“Hello”); } } OUTPUT: Hello |
3.Java Functional Interfaces
Ø An Interface that contains exactly one abstract method is known as functional interface.
Ø It can have any number of default, static methods but can contain only one abstract method. It can also declare methods of object class.
Ø Functional Interface also known as Single Abstract Method Interfaces or SAM Interfaces. It is a new feature in Java, which helps to achieve functional programming approach.
Example:
| @FunctionalInterface interface sayable{ void say(String msg); } public class FunctionalInterfaceExample implements sayable{ public void say(String msg){ System.out.println(msg); } public static void main(String[] args) { FunctionalInterfaceExample fie = new FunctionalInterfaceExample(); fie.say(“Hello there”); } } Output: Hello there |
Example:
A functional interface can have methods of object class. See in the following example
| @FunctionalInterface interface sayable{ void say(String msg); // abstract method // It can contain any number of methods of Object class. int hashCode(); String toString(); boolean equals(Object obj); } public class FunctionalInterfaceExample implements sayable{ public void say(String msg){ System.out.println(msg); } public static void main(String[] args) { FunctionalInterfaceExample fie = new FunctionalInterfaceExample(); fie.say(“Hello there”); } } Output: Hello there |
Note: A functional interface can extends to other interface only when that does not have any abstract method.
Example:
Invalid Functional Interface:
| interface sayable{ void say(String msg); // abstract method } @FunctionalInterface interface doable extends sayable{ // Invalid ‘@FunctionalInterface’ annotation; doable is not a functional interface void doIt(); } OUTPUT: compile time error. //Because doable interface is not functional interface. |
Example:
In the following example, a functional interface is extending to a
non-functional interface.
| interface Doable{ default void doit(){ System.out.println(“doit it now”); }}@FunctionalInterfaceinterface Sayable extends Doable{ void say(String msg);}class FunctionalInterfaceEXAmple implements Sayable{ public void say(String msg){ System.out.println(msg); } public static void main (String[] args) { FunctionalInterfaceEXAmple obj=new FunctionalInterfaceEXAmple(); obj.say(“hello param”); obj.doit(); }}Output:hello paramdoit it now |
Java predefine functional interface:
4.Java 8 Stream
5. Java Stream filter
Java stream provides a method filter () to filter stream elements on the basis of given predicate. Suppose you want to get only even elements of your list then you can do this easily with the help of filter method.
This method takes predicate as an argument and returns a stream of consisting of resulted elements.
Signature
| Stream<T> filter(Predicate<? super T> predicate) |
Predicate: It takes Predicate reference as an argument. Predicate is a functional Interface.
So, you can also pass lambda expression
It returns a new stream.
| 1. productsList.stream() 2. .filter(p ->p.price> 30000) // filtering price 3. .map(pm ->pm.price) // fetching price 4. .forEach(System.out::println); // iterating price |
6. Java encoder
https://www.javatpoint.com/java-base64-encode-decode
Java provides a facility to create default methods inside the interface. Methods which are defined inside the interface and tagged with default are known as default methods. These methods are non-abstract methods.
Example:
In the following example, Sayable is a functional interface that contains a default and an abstract method. The concept of default method is used to define a method with default implementation. You can override default method also to provide more specific implementation for the method.
| interface Sayable { default void defaultSay(){ System.out.println(“inside Default method”); } void hello();1. static void sayLouder(String msg){ 2. System.out.println(msg); 3. } }class Codechef implements Sayable{ public void hello(){ System.out.println(“hello method”); } public static void main (String[] args) throws java.lang.Exception { // Codechef c =new Codechef(); c.hello(); c.defaultSay(); Sayable. sayLouder(“Hello”); }}Output: hello methodinside Default methodHello |
Static Methods inside Java 8 Interface
You can also define static methods inside the interface. Static methods are used to define utility methods. Please refer above code for static code.
8. Java forEach Method:
Java provides a new method forEach() to iterate the elements. It is defined in Iterable and Stream interface. It is a default method defined in the Iterable interface. Collection classes which extends Iterable interface can use forEach loop to iterate elements.
This method takes a single parameter which is a functional interface. So, you can pass lambda expression as an argument.
| 1. default void forEach(Consumer<super T>action) |
| 1. List<String> gamesList = new ArrayList<String>(); 2. gamesList.add(“Football”); 3. gamesList.add(“Cricket”); 4. gamesList.add(“Chess”); 5. gamesList.add(“Hocky”); 6. System.out.println(“————Iterating by passing lambda expression————–“); 7. gamesList.forEach(games -> System.out.println(games)); 8. OR9. gamesList.forEach(System.out::println); |
Java Stream forEachOrdered () Method
Along with forEach () method, Java provides one more method forEachOrdered (). It is used to iterate elements in the order specified by the stream.
| 1. System.out.println(“————Iterating by passing lambda expression—————“); 2. gamesList.stream().forEachOrdered(games -> System.out.println(games)); 3. System.out.println(“————Iterating by passing method reference—————“); 4. gamesList.stream().forEachOrdered(System.out::println); |
9. Collectors
Collectors is a final class that extends Object class. It provides reduction operations, such as accumulating elements into collections, summarizing elements according to various criteria, etc.
https://www.javatpoint.com/java-8-collectors
10. String Joiner
Java added a new final class StringJoiner in java.util package. It is used to construct a sequence of characters separated by a delimiter. Now, you can create string by passing delimiters like comma (,), hyphen (-) etc. You can also pass prefix and suffix to the char sequence.
Add method:
| StringJoiner joinNames = new StringJoiner(“,”); // passing comma(,) as delimiter // Adding values to StringJoiner joinNames.add(“Rahul”); joinNames.add(“Raju”); joinNames.add(“Peter”); joinNames.add(“Raheem”); System.out.println(joinNames);Result:Rahul,Raju,Peter,Raheem |
Add prefix and suffix Method:
| StringJoiner joinNames = new StringJoiner(“,”, “[“, “]”); Result:[Rahul,Raju,Peter,Raheem] |
Merge two string:
| StringJoiner joinNames = new StringJoiner(“,”); // passing comma(,) as delimiter // Adding values to StringJoiner joinNames.add(“Rahul”); joinNames.add(“Raju”); joinNames.add(“Peter”); joinNames.add(“Raheem”); StringJoiner joinNames2 = new StringJoiner(“:”, “[“, “]”); // passing colon(:) and square-brackets as delimiter // Adding values to StringJoiner joinNames2.add(“Peter”); joinNames2.add(“Raheem”); StringJoiner merge = joinNames.merge(joinNames2); System.out.println(merge);Rahul,Raju,Peter,Raheem,Peter:Raheem |
11. Java Optional class
Java introduced a new class Optional in jdk8. It is a public final class and used to deal with NullPointerException in Java application. You must import java.util package to use this class. It provides methods which are used to check the presence of value for particular variable.
https://www.javatpoint.com/java-8-optional
| String [] str = new String [10]; Optional<String> checkNull = Optional.ofNullable(str[5]); if(checkNull.isPresent()){ // check for value is present or not String lowercaseString = str[5].toLowerCase(); System.out.print(lowercaseString); }else System.out.println(“string value is not present”);Output:string value is not present |
| 1. String[] str = new String[10]; 2. str[5] = “JAVA OPTIONAL CLASS EXAMPLE”; // Setting value for 5th index 3. Optional<String> checkNull = Optional.ofNullable(str[5]); 4. checkNull.ifPresent(System.out::println); // printing value by using method reference 5. System.out.println(checkNull.get()); // printing value by using get method 6. System.out.println(str[5].toLowerCase()); Output:JAVA OPTIONAL CLASS EXAMPLEJAVA OPTIONAL CLASS EXAMPLEjava optional class example |
12. Java Nashorn
https://www.javatpoint.com/java-nashorn
13. Java Parallel Array Sorting
Java provides a new additional feature in Array class which is used to sort array elements parallel. New methods has added to java.util.Arrays package that use the JSR 166 Fork/Join parallelism common pool to provide sorting of arrays in parallel. The methods are called parallelSort () and are overloaded for all the primitive data types and Comparable objects.
| 1. int[] arr = {5,8,1,0,6,9}; 2. // Iterating array elements 3. for (int i : arr) { 4. System.out.print(i+” “); 5. } 6. // Sorting array elements parallel 7. Arrays.parallelSort(arr); 8. System.out.println(“\nArray elements after sorting”); 9. // Iterating array elements 10. for (int i : arr) { 11. System.out.print(i+” “); 12. } output:5 8 1 0 6 9Array elements after sorting0 1 5 6 8 9 |
Java Parallel Array Sorting Example: Passing Start and End Index
| Arrays.parallelSort(arr,0,3); Output:5 8 1 0 6 9Array elements after sorting1 5 8 0 6 9 |
14. Java Type Inference
https://www.javatpoint.com/java-8-type-inference
15. Method Parameter reflection
https://www.javatpoint.com/java-8-method-parameter-reflection
16. Java type annotation
https://www.javatpoint.com/java-8-type-annotations-and-repeating-annotations
17. Java jdbc improvement