Pages

Tuesday, July 2, 2019

Java 8: Working with Supplier

1. Overview

In this tutorial, We'll learn about java 8 Supplier Functional Interface.

Supplier is part of package java.util.function. This is introduced in Java 8 as part of Function programming.

Api Reference

Supplier Functional Interface has only one Abstract method.


T get()

Where T -  the type of results supplied by this supplier

Java 8 - Working with Supplier


This method is called as Functional Method.

Supplier does not take any argument but returns a value always. Because of this named as Supplier as supplies everytime something when we call get() method.

Suppliers are very useful when we do not need to supply any value but need to return a value at the same time.



2. Example to generate random number using Supplier


Now, We will see how to use Supplier to get the randome number using Math class.

Math class a static method random() that returns a random value between 0.0 and 1.0.

In previous article, We have discussed Lambda Expressions. We must have an idea about Lambda to work with Functional Interface.

Supplier randomSupplier = () -> Math.random();


Just take a look at the above functional code that Supplier returns Double value.

How to know the type of the value.

This is very simple to find. Just see what type is retuned by lambda exp, that value we shuould mention as part of the Supplier declaration.

Next, We should call the get() method. 

System.out.println("Random value 1 "+randomSupplier.get());


Once get() method is invoked then immediately lambda will be executed automatically and excutes Math.random() method which returns a random value.

See the below output.

Output:

Random value 1 0.9235006477846478

Note: get() method can be called multiple times on supplier.

The below code is completely valid.

System.out.println("Random value 2 "+randomSupplier.get());
System.out.println("Random value 3 "+randomSupplier.get());
System.out.println("Random value 4 "+randomSupplier.get());
System.out.println("Random value 5 "+randomSupplier.get());

Produces the below output.

Random value 2 0.26474106955613286
Random value 3 0.2613837445870235
Random value 4 0.41373430220646323
Random value 5 0.4281632448845335

3. Supplier Example to fix "stream has already been operated upon or closed"

Observe the below code that works fine.

List fruits = Arrays.asList("Mango", "Jack Fruit", "Water Melon", "Apple");
Stream stream = fruits.stream();

Optional anyFruitName = stream.findAny();
System.out.println(anyFruitName.get());


Output:

Apple

But, If we perform any operation stream again then we will get runtime exception.

Optional firstFruitName = stream.findFirst();

Exception:

java.lang.IllegalStateException: stream has already been operated upon or closed
 at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229)
 at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:543)
 at com.java.w3schools.blog.java8.functional.SupplierStreamFix.main(SupplierStreamFix.java:17)

Here, the problem is performing the operations on stream which is already closed.

To fix this issue, we need to recreate a new Stream object.

See the complete article on "java.lang.IllegalStateException: stream has already been operated upon or closed"

This problem can be solved using Supplier as below instead of repeating the code twice to create the Stream object from fruits list.

Supplier> streamSupplier = () -> fruits.stream();

Stream anyStream = streamSupplier.get();
System.out.println("anyStream " + anyStream.findAny().get());

Stream firstStream = streamSupplier.get();
System.out.println("firstStream : " + firstStream.findAny().get());

4. Method Reference

Suppliers can be used with Method Reference.


//Mehtod Reference

Supplier methodRef = String::new;

Here, It calls the no-arg constructor.

If we want to call the argument constructor then there is a limitation for Supplier.

Note: That's just a limitation of the method reference syntax that you can't pass in any of the arguments. It's just how the syntax works.

5. Conclusion


In this article, We've studied about Supplier Functional Intetface added to java 8. Supplier has only one get() abstract method and should be used with Lambda for best practicies.

Seen the example program to get the random number and fix to a common error working with streams "java.lang.IllegalStateException: stream has already been operated upon or closed"

And also seen a note on Method Reference.

All the code shown in this post is over GitHub.

No comments:

Post a Comment

Please do not add any spam links in the comments section.