Java 8: Without Lambda Expression

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 36

Java 8

Java 8 Features

1. Lambda expressions:

 The Lambda expression is used to provide the implementation of an interface


which has functional interface. It saves a lot of code. In case of lambda
expression, we don't need to define the method again for providing the
implementation. Here, we just write the implementation code.

 Java lambda expression is treated as a function, so compiler does not


create .class file.

 Use of lambda expression is to provide the implementation of Functional


interface,Less coding.

Syntax: (argument-list) -> {body}

Without Lambda Expression

1. interface Drawable{
2. public void draw();
3. }
4. public class LambdaExpressionExample {
5. public static void main(String[] args) {
6. int width=10;
7.
8. //without lambda, Drawable implementation using anonymous class
9. Drawable d=new Drawable(){
10. public void draw(){System.out.println("Drawing "+width);}
11. };
12. d.draw();
13. }
14. }

With Lambda Exp:


1. @FunctionalInterface //It is optional
2. interface Drawable{
3. public void draw();
4. }
5.
6. public class LambdaExpressionExample2 {
7. public static void main(String[] args) {
8. int width=10;
9.
10. //with lambda
11. Drawable d2=()->{
12. System.out.println("Drawing "+width);
13. };
14. d2.draw();
15. }
16. }

Java Lambda Expression Example: Single Parameter

1. interface Sayable{
2. public String say(String name);
3. }
4.
5. public class LambdaExpressionExample4{
6. public static void main(String[] args) {
7.
8. // Lambda expression with single parameter.
9. Sayable s1=(name)->{
10. return "Hello, "+name;
11. };
12. System.out.println(s1.say("Sonoo"));
13.
14. // You can omit function parentheses
15. Sayable s2= name ->{
16. return "Hello, "+name;
17. };
18. System.out.println(s2.say("Sonoo"));
19. }
20. }

Java Lambda Expression Example: Multiple Parameters

1. interface Addable{
2. int add(int a,int b);
3. }
4.
5. public class LambdaExpressionExample5{
6. public static void main(String[] args) {
7.
8. // Multiple parameters in lambda expression
9. Addable ad1=(a,b)->(a+b);
10. System.out.println(ad1.add(10,20));
11.
12. // Multiple parameters with data type in lambda expression
13. Addable ad2=(int a,int b)->(a+b);
14. System.out.println(ad2.add(100,200));
15. }
16. }

Java Lambda Expression Example: with or without return


keyword
In Java lambda expression, if there is only one statement, you may or may not use
return keyword. You must use return keyword when lambda expression contains multiple
statements.

1. interface Addable{
2. int add(int a,int b);
3. }
4.
5. public class LambdaExpressionExample6 {
6. public static void main(String[] args) {
7.
8. // Lambda expression without return keyword.
9. Addable ad1=(a,b)->(a+b);
10. System.out.println(ad1.add(10,20));
11.
12. // Lambda expression with return keyword.
13. Addable ad2=(int a,int b)->{
14. return (a+b);
15. };
16. System.out.println(ad2.add(100,200));
17. }
18. }
Java Lambda Expression Example: Foreach Loop

1. import java.util.*;
2. public class LambdaExpressionExample7{
3. public static void main(String[] args) {
4.
5. List<String> list=new ArrayList<String>();
6. list.add("ankit");
7. list.add("mayank");
8. list.add("irfan");
9. list.add("jai");
10.
11. list.forEach(
12. (n)->System.out.println(n)
13. );
14. }
15. }

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.

1. public class LambdaExpressionExample9{


2. public static void main(String[] args) {
3.
4. //Thread Example without lambda
5. Runnable r1=new Runnable(){
6. public void run(){
7. System.out.println("Thread1 is running...");
8. }
9. };
10. Thread t1=new Thread(r1);
11. t1.start();
12. //Thread Example with lambda
13. Runnable r2=()->{
14. System.out.println("Thread2 is running...");
15. };
16. Thread t2=new Thread(r2);
17. t2.start();
18. }
19. }

Java Lambda Expression Example: Comparator

1. import java.util.ArrayList;
2. import java.util.Collections;
3. import java.util.List;
4. class Product{
5. int id;
6. String name;
7. float price;
8. public Product(int id, String name, float price) {
9. super();
10. this.id = id;
11. this.name = name;
12. this.price = price;
13. }
14. }
15. public class LambdaExpressionExample10{
16. public static void main(String[] args) {
17. List<Product> list=new ArrayList<Product>();
18.
19. //Adding Products
20. list.add(new Product(1,"HP Laptop",25000f));
21. list.add(new Product(3,"Keyboard",300f));
22. list.add(new Product(2,"Dell Mouse",150f));
23.
24. System.out.println("Sorting on the basis of name...");
25.
26. // implementing lambda expression
27. Collections.sort(list,(p1,p2)->{
28. return p1.name.compareTo(p2.name);
29. });
30. for(Product p:list){
31. System.out.println(p.id+" "+p.name+" "+p.price);
32. }
33.
34. }
35. }
Java Lambda Expression Example: Filter Collection Data

1. import java.util.ArrayList;
2. import java.util.List;
3. import java.util.stream.Stream;
4. class Product{
5. int id;
6. String name;
7. float price;
8. public Product(int id, String name, float price) {
9. super();
10. this.id = id;
11. this.name = name;
12. this.price = price;
13. }
14. }
15. public class LambdaExpressionExample11{
16. public static void main(String[] args) {
17. List<Product> list=new ArrayList<Product>();
18. list.add(new Product(1,"Samsung A5",17000f));
19. list.add(new Product(3,"Iphone 6S",65000f));
20. list.add(new Product(2,"Sony Xperia",25000f));
21. list.add(new Product(4,"Nokia Lumia",15000f));
22. list.add(new Product(5,"Redmi4 ",26000f));
23. list.add(new Product(6,"Lenevo Vibe",19000f));
24.
25. // using lambda to filter data
26. Stream<Product> filtered_data = list.stream().filter(p -> p.price > 20000);

27.
28. // using lambda to iterate through collection
29. filtered_data.forEach(
30. product -> System.out.println(product.name+": "+product.price)
31. );
32. }
33. }

Java Lambda Expression Example: Event Listener


1. import javax.swing.JButton;
2. import javax.swing.JFrame;
3. import javax.swing.JTextField;
4. public class LambdaEventListenerExample {
5. public static void main(String[] args) {
6. JTextField tf=new JTextField();
7. tf.setBounds(50, 50,150,20);
8. JButton b=new JButton("click");
9. b.setBounds(80,100,70,30);
10.
11. // lambda expression implementing here.
12. b.addActionListener(e-> {tf.setText("hello swing");});
13.
14. JFrame f=new JFrame();
15. f.add(tf);f.add(b);
16. f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
17. f.setLayout(null);
18. f.setSize(300, 200);
19. f.setVisible(true);
20.
21. }

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. In this tutorial, we are
explaining method reference concept in detail.

Types of Method References


There are following types of method references in java:

1. Reference to a static method.

2. Reference to an instance method.

3. Reference to a constructor.
1) Reference to a Static Method
You can refer to static method defined in the class. Following is the syntax and example
which describe the process of referring static method in Java.

Syntax

1. ContainingClass::staticMethodName
Example 1

In the following example, we have defined a functional interface and referring a static
method to it's functional method say().

1. interface Sayable{
2. void say();
3. }
4. public class MethodReference {
5. public static void saySomething(){
6. System.out.println("Hello, this is static method.");
7. }
8. public static void main(String[] args) {
9. // Referring static method
10. Sayable sayable = MethodReference::saySomething;
11. // Calling interface method
12. sayable.say();
13. }
14. }
Test it Now

Output:

Hello, this is static method.

Example 2

In the following example, we are using predefined functional interface Runnable to refer
static method.

1. public class MethodReference2 {


2. public static void ThreadStatus(){
3. System.out.println("Thread is running...");
4. }
5. public static void main(String[] args) {
6. Thread t2=new Thread(MethodReference2::ThreadStatus);
7. t2.start();
8. }
9. }
Test it Now

Output:

Thread is running...

Example 3

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.

1. import java.util.function.BiFunction;
2. class Arithmetic{
3. public static int add(int a, int b){
4. return a+b;
5. }
6. }
7. public class MethodReference3 {
8. public static void main(String[] args) {
9. BiFunction<Integer, Integer, Integer>adder = Arithmetic::add;
10. int result = adder.apply(10, 20);
11. System.out.println(result);
12. }
13. }
Test it Now

Output:

30

Example 4

You can also override static methods by referring methods. In the following example, we
have defined and overloaded three add methods.

1. import java.util.function.BiFunction;
2. class Arithmetic{
3. public static int add(int a, int b){
4. return a+b;
5. }
6. public static float add(int a, float b){
7. return a+b;
8. }
9. public static float add(float a, float b){
10. return a+b;
11. }
12. }
13. public class MethodReference4 {
14. public static void main(String[] args) {
15. BiFunction<Integer, Integer, Integer>adder1 = Arithmetic::add;
16. BiFunction<Integer, Float, Float>adder2 = Arithmetic::add;
17. BiFunction<Float, Float, Float>adder3 = Arithmetic::add;
18. int result1 = adder1.apply(10, 20);
19. float result2 = adder2.apply(10, 20.0f);
20. float result3 = adder3.apply(10.0f, 20.0f);
21. System.out.println(result1);
22. System.out.println(result2);
23. System.out.println(result3);
24. }
25. }
Test it Now

Output:

30
30.0
30.0

2) Reference to an Instance Method


like static methods, you can refer instance methods also. In the following example, we
are describing the process of referring the instance method.

Syntax

1. containingObject::instanceMethodName
Example 1
In the following example, we are referring non-static methods. You can refer methods by
class object and anonymous object.

1. interface Sayable{
2. void say();
3. }
4. public class InstanceMethodReference {
5. public void saySomething(){
6. System.out.println("Hello, this is non-static method.");
7. }
8. public static void main(String[] args) {
9. InstanceMethodReference methodReference = new InstanceMethodReferen
ce(); // Creating object
10. // Referring non-static method using reference
11. Sayable sayable = methodReference::saySomething;
12. // Calling interface method
13. sayable.say();
14. // Referring non-static method using anonymous object
15. Sayable sayable2 = new InstanceMethodReference()::saySomething; //
You can use anonymous object also
16. // Calling interface method
17. sayable2.say();
18. }
19. }
Test it Now

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.

1. public class InstanceMethodReference2 {


2. public void printnMsg(){
3. System.out.println("Hello, this is instance method");
4. }
5. public static void main(String[] args) {
6. Thread t2=new Thread(new InstanceMethodReference2()::printnMsg);
7. t2.start();
8. }
9. }
Test it Now
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.

1. import java.util.function.BiFunction;
2. class Arithmetic{
3. public int add(int a, int b){
4. return a+b;
5. }
6. }
7. public class InstanceMethodReference3 {
8. public static void main(String[] args) {
9. BiFunction<Integer, Integer, Integer>adder = new Arithmetic()::add;
10. int result = adder.apply(10, 20);
11. System.out.println(result);
12. }
13. }
Test it Now

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

1. ClassName::new
Example:
1. interface Messageable{
2. Message getMessage(String msg);
3. }
4. class Message{
5. Message(String msg){
6. System.out.print(msg);
7. }
8. }
9. public class ConstructorReference {
10. public static void main(String[] args) {
11. Messageable hello = Message::new;
12. hello.getMessage("Hello");
13. }
14. }

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 is 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 1
1. @FunctionalInterface
2. interface sayable{
3. void say(String msg);
4. }
5. public class FunctionalInterfaceExample implements sayable{
6. public void say(String msg){
7. System.out.println(msg);
8. }
9. public static void main(String[] args) {
10. FunctionalInterfaceExample fie = new FunctionalInterfaceExample();
11. fie.say("Hello there");
12. }
13. }
Test it Now

Output:

Hello there

A functional interface can have methods of object class. See in the following example.
Example 2
1.
2. @FunctionalInterface
3. interface sayable{
4. void say(String msg); // abstract method
5. // It can contain any number of Object class methods.
6. int hashCode();
7. String toString();
8. boolean equals(Object obj);
9. }
10. public class FunctionalInterfaceExample2 implements sayable{
11. public void say(String msg){
12. System.out.println(msg);
13. }
14. public static void main(String[] args) {
15. FunctionalInterfaceExample2 fie = new FunctionalInterfaceExample2();
16. fie.say("Hello there");
17. }
18. }
Test it Now

Output:

Hello there

Invalid Functional Interface


A functional interface can extends another interface only when it does not have any
abstract method.

1. interface sayable{
2. void say(String msg); // abstract method
3. }
4. @FunctionalInterface
5. interface Doable extends sayable{
6. // Invalid '@FunctionalInterface' annotation; Doable is not a functional interfac
e
7. void doIt();
8. }

Output:

compile-time error
Example 3
In the following example, a functional interface is extending to a non-functional
interface.

1. interface Doable{
2. default void doIt(){
3. System.out.println("Do it now");
4. }
5. }
6. @FunctionalInterface
7. interface Sayable extends Doable{
8. void say(String msg); // abstract method
9. }
10. public class FunctionalInterfaceExample3 implements Sayable{
11. public void say(String msg){
12. System.out.println(msg);
13. }
14. public static void main(String[] args) {
15. FunctionalInterfaceExample3 fie = new FunctionalInterfaceExample3();
16. fie.say("Hello there");
17. fie.doIt();
18. }
19. }

Java 8 Stream
Java provides a new additional package in Java 8 called java.util.stream. This package
consists of classes, interfaces and enum to allows functional-style operations on the
elements. You can use stream by importing java.util.stream package.

Stream provides following features:

o Stream does not store elements. It simply conveys elements from a source such
as a data structure, an array, or an I/O channel, through a pipeline of
computational operations.

o Stream is functional in nature. Operations performed on a stream does not


modify it's source. For example, filtering a Stream obtained from a collection
produces a new Stream without the filtered elements, rather than removing
elements from the source collection.

o Stream is lazy and evaluates code only when required.

o The elements of a stream are only visited once during the life of a stream. Like an
Iterator, a new stream must be generated to revisit the same elements of the
source.

You can use stream to filter, collect, print, and convert from one data structure to other
etc. In the following examples, we have apply various operations with the help of
stream.

Java Stream Example: Filtering Collection by using


Stream
Here, we are filtering data by using stream. You can see that code is optimized and
maintained. Stream provides fast execution.

1. import java.util.*;
2. import java.util.stream.Collectors;
3. class Product{
4. int id;
5. String name;
6. float price;
7. public Product(int id, String name, float price) {
8. this.id = id;
9. this.name = name;
10. this.price = price;
11. }
12. }
13. public class JavaStreamExample {
14. public static void main(String[] args) {
15. List<Product> productsList = new ArrayList<Product>();
16. //Adding Products
17. productsList.add(new Product(1,"HP Laptop",25000f));
18. productsList.add(new Product(2,"Dell Laptop",30000f));
19. productsList.add(new Product(3,"Lenevo Laptop",28000f));
20. productsList.add(new Product(4,"Sony Laptop",28000f));
21. productsList.add(new Product(5,"Apple Laptop",90000f));
22. List<Float> productPriceList2 =productsList.stream()
23. .filter(p -> p.price > 30000)// filtering data
24. .map(p->p.price) // fetching price
25. .collect(Collectors.toList()); // collecting as list
26. System.out.println(productPriceList2);
27. }
28. }

Output:

[90000.0]

Java Stream Iterating Example


You can use stream to iterate any number of times. Stream provides predefined
methods to deal with the logic you implement. In the following example, we are
iterating, filtering and passed a limit to fix the iteration.

1. import java.util.stream.*;
2. public class JavaStreamExample {
3. public static void main(String[] args){
4. Stream.iterate(1, element->element+1)
5. .filter(element->element%5==0)
6. .limit(5)
7. .forEach(System.out::println);
8. }
9. }

Output:

5
10
15
20
25

Java Stream Example: Filtering and Iterating


Collection
In the following example, we are using filter() method. Here, you can see code is
optimized and very concise.

1. import java.util.*;
2. class Product{
3. int id;
4. String name;
5. float price;
6. public Product(int id, String name, float price) {
7. this.id = id;
8. this.name = name;
9. this.price = price;
10. }
11. }
12. public class JavaStreamExample {
13. public static void main(String[] args) {
14. List<Product> productsList = new ArrayList<Product>();
15. //Adding Products
16. productsList.add(new Product(1,"HP Laptop",25000f));
17. productsList.add(new Product(2,"Dell Laptop",30000f));
18. productsList.add(new Product(3,"Lenevo Laptop",28000f));
19. productsList.add(new Product(4,"Sony Laptop",28000f));
20. productsList.add(new Product(5,"Apple Laptop",90000f));
21. // This is more compact approach for filtering data
22. productsList.stream()
23. .filter(product -> product.price == 30000)
24. .forEach(product -> System.out.println(product.name));
25. }
26. }

Output:

Dell Laptop

Java Stream Example : reduce() Method in


Collection
This method takes a sequence of input elements and combines them into a single
summary result by repeated operation. For example, finding the sum of numbers, or
accumulating elements into a list.

In the following example, we are using reduce() method, which is used to sum of all the
product prices.

1. import java.util.*;
2. class Product{
3. int id;
4. String name;
5. float price;
6. public Product(int id, String name, float price) {
7. this.id = id;
8. this.name = name;
9. this.price = price;
10. }
11. }
12. public class JavaStreamExample {
13. public static void main(String[] args) {
14. List<Product> productsList = new ArrayList<Product>();
15. //Adding Products
16. productsList.add(new Product(1,"HP Laptop",25000f));
17. productsList.add(new Product(2,"Dell Laptop",30000f));
18. productsList.add(new Product(3,"Lenevo Laptop",28000f));
19. productsList.add(new Product(4,"Sony Laptop",28000f));
20. productsList.add(new Product(5,"Apple Laptop",90000f));
21. // This is more compact approach for filtering data
22. Float totalPrice = productsList.stream()
23. .map(product->product.price)
24. .reduce(0.0f,(sum, price)->sum+price); // accumulating price
25. System.out.println(totalPrice);
26. // More precise code
27. float totalPrice2 = productsList.stream()
28. .map(product->product.price)
29. .reduce(0.0f,Float::sum); // accumulating price, by referring method
of Float class
30. System.out.println(totalPrice2);
31.
32. }
33. }

Output:

201000.0
201000.0

Java Stream Example: Sum by using Collectors


Methods
We can also use collectors to compute sum of numeric values. In the following example,
we are using Collectors class and it?s specified methods to compute sum of all the
product prices.
1. import java.util.*;
2. import java.util.stream.Collectors;
3. class Product{
4. int id;
5. String name;
6. float price;
7. public Product(int id, String name, float price) {
8. this.id = id;
9. this.name = name;
10. this.price = price;
11. }
12. }
13. public class JavaStreamExample {
14. public static void main(String[] args) {
15. List<Product> productsList = new ArrayList<Product>();
16. //Adding Products
17. productsList.add(new Product(1,"HP Laptop",25000f));
18. productsList.add(new Product(2,"Dell Laptop",30000f));
19. productsList.add(new Product(3,"Lenevo Laptop",28000f));
20. productsList.add(new Product(4,"Sony Laptop",28000f));
21. productsList.add(new Product(5,"Apple Laptop",90000f));
22. // Using Collectors's method to sum the prices.
23. double totalPrice3 = productsList.stream()
24. .collect(Collectors.summingDouble(product->product.price));
25. System.out.println(totalPrice3);
26.
27. }
28. }

Output:

201000.0

Java Stream Example: Find Max and Min Product


Price
Following example finds min and max product price by using stream. It provides
convenient way to find values without using imperative approach.

1. import java.util.*;
2. class Product{
3. int id;
4. String name;
5. float price;
6. public Product(int id, String name, float price) {
7. this.id = id;
8. this.name = name;
9. this.price = price;
10. }
11. }
12. public class JavaStreamExample {
13. public static void main(String[] args) {
14. List<Product> productsList = new ArrayList<Product>();
15. //Adding Products
16. productsList.add(new Product(1,"HP Laptop",25000f));
17. productsList.add(new Product(2,"Dell Laptop",30000f));
18. productsList.add(new Product(3,"Lenevo Laptop",28000f));
19. productsList.add(new Product(4,"Sony Laptop",28000f));
20. productsList.add(new Product(5,"Apple Laptop",90000f));
21. // max() method to get max Product price
22. Product productA = productsList.stream()
23. .max((product1, product2)->
24. product1.price > product2.price ? 1: -1).get();
25.
26. System.out.println(productA.price);
27. // min() method to get min Product price
28. Product productB = productsList.stream()
29. .max((product1, product2)->
30. product1.price < product2.price ? 1: -1).get();
31. System.out.println(productB.price);
32.
33. }
34. }

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.

Syntax:

Stream<T> filter(Predicate<? super T> predicate)


Java Base64 Encode and Decode
Java provides a class Base64 to deal with encryption. You can encrypt and decrypt your
data by using provided methods. You need to import java.util.Base64 in your source file
to use its methods.

This class provides three different encoders and decoders to encrypt information at each
level. You can use these methods at the following levels.

Basic Encoding and Decoding


It uses the Base64 alphabet specified by Java in RFC 4648 and RFC 2045 for encoding
and decoding operations. The encoder does not add any line separator character. The
decoder rejects data that contains characters outside the base64 alphabet.

URL and Filename Encoding and Decoding


It uses the Base64 alphabet specified by Java in RFC 4648 for encoding and decoding
operations. The encoder does not add any line separator character. The decoder rejects
data that contains characters outside the base64 alphabet.

MIME
It uses the Base64 alphabet as specified in RFC 2045 for encoding and decoding
operations. The encoded output must be represented in lines of no more than 76
characters each and uses a carriage return '\r' followed immediately by a linefeed '\n' as
the line separator. No line separator is added to the end of the encoded output. All line
separators or other characters not found in the base64 alphabet table are ignored in
decoding operation.

Example:

Java Base64 Example: Basic Encoding and


Decoding
1. import java.util.Base64;
2. publicclass Base64BasicEncryptionExample {
3. publicstaticvoid main(String[] args) {
4. // Getting encoder
5. Base64.Encoder encoder = Base64.getEncoder();
6. // Creating byte array
7. bytebyteArr[] = {1,2};
8. // encoding byte array
9. bytebyteArr2[] = encoder.encode(byteArr);
10. System.out.println("Encoded byte array: "+byteArr2);
11. bytebyteArr3[] = newbyte[5]; // Make sure it has enough size to
store copied bytes
12. intx = encoder.encode(byteArr,byteArr3); // Returns number of bytes writ
ten
13. System.out.println("Encoded byte array written to another array: "+byteArr
3);
14. System.out.println("Number of bytes written: "+x);
15.
16. // Encoding string
17. String str = encoder.encodeToString("JavaTpoint".getBytes());
18. System.out.println("Encoded string: "+str);
19. // Getting decoder
20. Base64.Decoder decoder = Base64.getDecoder();
21. // Decoding string
22. String dStr = new String(decoder.decode(str));
23. System.out.println("Decoded string: "+dStr);
24. }
25. }

Java Default Methods

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.

Java Default Method 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.

Let's see a simple

1. interface Sayable{
2. // Default method
3. default void say(){
4. System.out.println("Hello, this is default method");
5. }
6. // Abstract method
7. void sayMore(String msg);
8. }
9. public class DefaultMethods implements Sayable{
10. public void sayMore(String msg){ // implementing abstract method
11. System.out.println(msg);
12. }
13. public static void main(String[] args) {
14. DefaultMethods dm = new DefaultMethods();
15. dm.say(); // calling default method
16. dm.sayMore("Work is worship"); // calling abstract method
17.
18. }
19. }

Java forEach loop


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.

forEach() Signature in Iterable Interface


1. default void forEach(Consumer<super T>action)

Java 8 forEach() example 1


1. import java.util.ArrayList;
2. import java.util.List;
3. public class ForEachExample {
4. public static void main(String[] args) {
5. List<String> gamesList = new ArrayList<String>();
6. gamesList.add("Football");
7. gamesList.add("Cricket");
8. gamesList.add("Chess");
9. gamesList.add("Hocky");
10. System.out.println("------------Iterating by passing lambda expression------
--------");
11. gamesList.forEach(games -> System.out.println(games));
12.
13. }
14. }

Java 8 forEach() example 2


1. import java.util.ArrayList;
2. import java.util.List;
3. public class ForEachExample {
4. public static void main(String[] args) {
5. List<String> gamesList = new ArrayList<String>();
6. gamesList.add("Football");
7. gamesList.add("Cricket");
8. gamesList.add("Chess");
9. gamesList.add("Hocky");
10. System.out.println("------------Iterating by passing method reference--------
-------");
11. gamesList.forEach(System.out::println);
12. }

13. } 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.

Singnature:
1. void forEachOrdered(Consumer<? super T> action)

Java Stream forEachOrdered() Method Example


1. import java.util.ArrayList;
2. import java.util.List;
3. public class ForEachOrderedExample {
4. public static void main(String[] args) {
5. List<String> gamesList = new ArrayList<String>();
6. gamesList.add("Football");
7. gamesList.add("Cricket");
8. gamesList.add("Chess");
9. gamesList.add("Hocky");
10. System.out.println("------------Iterating by passing lambda expression------
---------");
11. gamesList.stream().forEachOrdered(games -> System.out.println(games));
12. System.out.println("------------Iterating by passing method reference--------
-------");
13. gamesList.stream().forEachOrdered(System.out::println);
14. }
15.
16. }

Java 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.

Java Collectors class provides various methods to deal with elements

Java Collectors Example: using sum method


1. import java.util.stream.Collectors;
2. import java.util.List;
3. import java.util.ArrayList;
4. class Product{
5. int id;
6. String name;
7. float price;
8.
9. public Product(int id, String name, float price) {
10. this.id = id;
11. this.name = name;
12. this.price = price;
13. }
14. }
15. public class CollectorsExample {
16. public static void main(String[] args) {
17. List<Product> productsList = new ArrayList<Product>();
18. //Adding Products
19. productsList.add(new Product(1,"HP Laptop",25000f));
20. productsList.add(new Product(2,"Dell Laptop",30000f));
21. productsList.add(new Product(3,"Lenevo Laptop",28000f));
22. productsList.add(new Product(4,"Sony Laptop",28000f));
23. productsList.add(new Product(5,"Apple Laptop",90000f));
24. Double sumPrices =
25. productsList.stream()
26. .collect(Collectors.summingDouble(x->x.price)); // collecting
as list
27. System.out.println("Sum of prices: "+sumPrices);
28. Integer sumId =
29. productsList.stream().collect(Collectors.summingInt(x->x.id));
30. System.out.println("Sum of id's: "+sumId);
31. }
32. }

Java StringJoiner
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.

StringJoiner Example: Merge Two StringJoiner


The merge() method merges two StringJoiner objects excluding of prefix and suffix of
second StringJoiner object.

1. // importing StringJoiner class


2. import java.util.StringJoiner;
3. public class StringJoinerExample {
4. public static void main(String[] args) {
5.
6. StringJoiner joinNames = new StringJoiner(",", "[", "]"); // passing comm
a(,) and square-brackets as delimiter
7.
8. // Adding values to StringJoiner
9. joinNames.add("Rahul");
10. joinNames.add("Raju");
11.
12. // Creating StringJoiner with :(colon) delimiter
13. StringJoiner joinNames2 = new StringJoiner(":", "[", "]"); // passing colon(
:) and square-brackets as delimiter
14.
15. // Adding values to StringJoiner
16. joinNames2.add("Peter");
17. joinNames2.add("Raheem");
18.
19. // Merging two StringJoiner
20. StringJoiner merge = joinNames.merge(joinNames2);
21. System.out.println(merge);
22. }
23. }

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.

Java Optional Example: If Value is Present


1. import java.util.Optional;
2. public class OptionalExample {
3. public static void main(String[] args) {
4. String[] str = new String[10];
5. str[5] = "JAVA OPTIONAL CLASS EXAMPLE";// Setting value for 5th index
6. Optional<String> checkNull = Optional.ofNullable(str[5]);
7. if(checkNull.isPresent()){ // It Checks, value is present or not
8. String lowercaseString = str[5].toLowerCase();
9. System.out.print(lowercaseString);
10. }else
11. System.out.println("String value is not present");
12. }
13. }

Java Nashorn
Nashorn is a JavaScript engine. It is used to execute JavaScript code dynamically at JVM
(Java Virtual Machine). Java provides a command-line tool jjs which is used to execute
JavaScript code.

You can execute JavaScript code by using jjs command-line tool and by embedding into
Java source code.
Example to execute js code:
Command: jjs hello.js

Example: Setting JavaScript variable in Java File


You can pass value to JavaScript variable in the Java file. In the followed example, we
are binding and passing variable to JavaScript file.

File: hello.js

1. print("Hello "+name);

File: NashornExample.java

1. import javax.script.*;
2. import java.io.*;
3. public class NashornExample {
4. public static void main(String[] args) throws Exception{
5. // Creating script engine
6. ScriptEngine ee = new ScriptEngineManager().getEngineByName("Nashorn"
);
7. //Binding script and Define scope of script
8. Bindings bind = ee.getBindings(ScriptContext.ENGINE_SCOPE);
9. bind.put("name", "Nashorn");
10. // Reading Nashorn file
11. ee.eval(new FileReader("js/hello.js"));
12. }
13. }

Import Java Package in JavaScript File


Java provides a facility to import Java package inside the JavaScript code. Here, we are
using two approaches to import Java packages.

Example1: Import Java Package in JavaScript File


File: hello.js

1. print(java.lang.Math.sqrt(4));
Output:

Example2: Import Java Package in JavaScript File


File: hello.js

1. var importFile = new JavaImporter(java.util);


2. var a = new importFile.ArrayList();
3. a.add(12);
4. a.add(20);
5. print(a);
6. print(a.getClass());

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.

Java Parallel Array Sorting Example: Passing Start and End Index:

1. import java.util.Arrays;
2. public class ParallelArraySorting {
3. public static void main(String[] args) {
4. // Creating an integer array
5. int[] arr = {5,8,1,0,6,9,50,-3};
6. // Iterating array elements
7. for (int i : arr) {
8. System.out.print(i+" ");
9. }
10. // Sorting array elements parallel and passing start, end index
11. Arrays.parallelSort(arr,0,4);
12. System.out.println("\nArray elements after sorting");
13. // Iterating array elements
14. for (int i : arr) {
15. System.out.print(i+" ");
16. }
17. }
18. }
19.

Java Type Inference


Type inference is a feature of Java which provides ability to compiler to look at each
method invocation and corresponding declaration to determine the type of arguments.

Java provides improved version of type inference in Java 8. the following example
explains, how we can use type inference in our code:

Here, we are creating arraylist by mentioning integer type explicitly at both side. The
following approach is used earlier versions of Java.

1. List<Integer> list = new ArrayList<Integer>();

In the following declaration, we are mentioning type of arraylist at one side. This
approach was introduce in Java 7. Here, you can left second side as blank diamond and
compiler will infer type of it by type of reference variable.

1. List<Integer> list2 = new ArrayList<>();

Improved Type Inference


In Java 8, you can call specialized method without explicitly mentioning of type of
arguments.

1. showList(new ArrayList<>());

example:

1. class GenericClass<X> {
2. X name;
3. public void setName(X name){
4. this.name = name;
5. }
6. public X getName(){
7. returnname;
8. }
9. public String genericMethod(GenericClass<String> x){
10. x.setName("John");
11. returnx.name;
12. }
13. }
14.
15. public class TypeInferenceExample {
16. public static void main(String[] args) {
17. GenericClass<String> genericClass = new GenericClass<String>();
18. genericClass.setName("Peter");
19. System.out.println(genericClass.getName());
20.
21. GenericClass<String> genericClass2 = new GenericClass<>();
22. genericClass2.setName("peter");
23. System.out.println(genericClass2.getName());
24.
25. // New improved type inference
26. System.out.println(genericClass2.genericMethod(new GenericClass<>()));
27. }
28. }

Method Parameter Reflection


Java provides a new feature in which you can get the names of formal parameters of any
method or constructor. The java.lang.reflect package contains all the required classes
like Method and Parameter to work with parameter reflection.

1. import java.lang.reflect.Method;
2. import java.lang.reflect.Parameter;
3. public class ParameterReflection {
4. public static void main(String[] args) {
5. // Creating object of a class
6. Calculate calculate = new Calculate();
7. // instantiating Class class
8. Classcls = calculate.getClass();
9. // Getting declared methods inside the Calculate class
10. Method[] method = cls.getDeclaredMethods(); // It returns array of method
s
11. // Iterating method array
12. for (Method method2 : method) {
13. System.out.print(method2.getName()); // getting name of method
14. // Getting parameters of each method
15. Parameter parameter[] = method2.getParameters(); // It returns array o
f parameters
16. // Iterating parameter array
17. for (Parameter parameter2 : parameter) {
18. System.out.print(""+parameter2.getParameterizedType()); // returns
type of parameter
19. System.out.print(""+parameter2.getName()); // returns parameter na
me
20. }
21. System.out.println();
22. }
23. }
24. }

Output:

mul int a int b


add int a int b

Above code will produce the below output if you don't use -parameters flag to compile
the Calculate.java file.

Output:

mul int arg0 int arg1

add int arg0 int arg1

Java Type and Repeating Annotations


Java Type Annotations
Java 8 has included two new features repeating and type annotations in its prior
annotations topic. In early Java versions, you can apply annotations only to declarations.
After releasing of Java SE 8 , annotations can be applied to any type use. It means that
annotations can be used anywhere you use a type. For example, if you want to avoid
NullPointerException in your code, you can declare a string variable like this:

@NonNull String str;


List<@NonNull String> str
@NonNull List<String>
@Encrypted File file
@Open Connection connection

void divideInteger(int a, int b) throws @ZeroDivisor ArithmeticException

Arrays<@NonNegative Integer> sort

Java Repeating Annotations


In Java 8 release, Java allows you to repeating annotations in your source code. It is
helpful when you want to reuse annotation for the same class. You can repeat an
annotation anywhere that you would use a standard annotation.

For compatibility reasons, repeating annotations are stored in a container annotation


that is automatically generated by the Java compiler. In order for the compiler to do this,
two declarations are required in your code.

1. Declare a repeatable annotation type

2. Declare the containing annotation type

1) Declare a repeatable annotation type


Declaring of repeatable annotation type must be marked with the @Repeatable meta-
annotation. In the following example, we have defined a custom @Game repeatable
annotation type.

1. @Repeatable(Games.class)
2. @interfaceGame{
3. String name();
4. String day();
5. }

The value of the @Repeatable meta-annotation, in parentheses, is the type of the


container annotation that the Java compiler generates to store repeating annotations. In
the following example, the containing annotation type is Games. So, repeating @Game
annotations is stored in an @Games annotation.

2) Declare the containing annotation type


Containing annotation type must have a value element with an array type. The
component type of the array type must be the repeatable annotation type. In the
following example, we are declaring Games containing annotation type:

1. @interfaceGames{
2. Game[] value();
3. }

Note - Compiler will throw a compile-time error, if you apply the same annotation to a declaration
without first declaring it as repeatable.

Java Repeating Annotations Example


1. // Importing required packages for repeating annotation
2. import java.lang.annotation.Repeatable;
3. import java.lang.annotation.Retention;
4. import java.lang.annotation.RetentionPolicy;
5. // Declaring repeatable annotation type
6. @Repeatable(Games.class)
7. @interfaceGame{
8. String name();
9. String day();
10. }
11. // Declaring container for repeatable annotation type
12. @Retention(RetentionPolicy.RUNTIME)
13. @interfaceGames{
14. Game[] value();
15. }
16. // Repeating annotation
17. @Game(name = "Cricket", day = "Sunday")
18. @Game(name = "Hockey", day = "Friday")
19. @Game(name = "Football", day = "Saturday")
20. public class RepeatingAnnotationsExample {
21. public static void main(String[] args) {
22. // Getting annotation by type into an array
23. Game[] game = RepeatingAnnotationsExample.class.getAnnotationsByType
(Game.class);
24. for (Gamegame2 : game) { // Iterating values
25. System.out.println(game2.name()+" on "+game2.day());
26. }
27. }
28. }

OUTPUT:

Cricket on Sunday
Hockey on Friday
Football on Saturday

Java 8 JDBC Improvements


In Java 8, Java made two major changes in JDBC API.

1.The JDBC-ODBC Bridge has been removed.


2) Added some new features in JDBC 4.2.

Java JDBC 4.2 introduces the following features:

o Addition of REF_CURSOR support.

o Addition of java.sql.DriverAction Interface

o Addition of security check on deregisterDriver Method in DriverManager Class

o Addition of the java.sql.SQLType Interface

o Addition of the java.sql.JDBCType Enum

o Add Support for large update counts

o Changes to the existing interfaces

o Rowset 1.2: Lists the enhancements for JDBC RowSet

You might also like