How to find the first element of Stream in Java 8 - findFirst() Example

In Java 8, you can use the Stream.findFirst() method to get the first element of Stream in Java. This is a terminal operation and often used after applying several intermediate operations e.g. filter, mapping, flattening etc. For example, if you have a List of String and you want to find the first String whose length is greater than 10, you can use the findFirst() method along with stream() and filter() to get that String. The stream() method gets the Stream from a List, which then allow you to apply several useful methods defined in the java.util.Stream class e.g. filter(), map(), flatMap() etc.

One of the important thing to know while using for writing such logic is that all intermediate operations e.g. filter(), map() etc are lazy and they are only executed when a terminal operation like findFirst() or forEach() is called.

This also means, a lot of opportunity for optimization depending upon the size of the original list. In this article, I'll show you a couple of examples of findFirst() method with Predicate to show the true power of Stream in Java 8.

You can also read Java SE 8 for Really Impatient for some really good example and explanation. Cay S. Horstmann has done a fabulous job on explaining tricky Java 8 concepts in simple words.



Java 8 findFirst() Example

Let's say, we have a List of String and we want to find out the first String which has the length greater than 10, how do you solve this problem before Java 8? Well, in Java 6 or 7 you can use the enhanced for loop as shown below to get the first String which satisfies our requirement as shown below:



for (String gadget : gadgets) {
  if (gadget.length() > 10) {
    System.out.println("Prior ot Java 8: " + gadget);
    break;
  }
}

In Java 8, you can achieve the same effect by using the findFirst() method of java.util.stream.Stream class as shown below:

String item = gadgets.stream()
    .filter(s -> s.length() > 10)
    .findFirst()
    .orElse("");

Many Java Programmers think that this is an inefficient approach because it looks like the filter() method is scanning the whole list as opposed to breaking on the first element as we have done in our prior to Java 8 example. This is not true, Java 8 example is as efficient as the one before. The filter() is an intermediate operation which is lazy and only evaluated when you call a terminal method e.g. forEach() method or findFirst() method as in this case.


This means, the filter() will not scan the whole list but only first few elements until it got the one whose length is greater than 10. You can verify this by using peek() method which prints output of what happening during stream processing steps as shown below:

String item = gadgets.stream()
     .peek(s -> System.out.println("processing: " + s))
     .filter(s -> s.length() >8)
     .findFirst()
     .orElse("");

Output:
processing: SmartPhone
result: SmartPhone

You can see that filter() has processed just one element from the Stream. Once it found the "SmartPhone", it stops because that satisfy the findFirst() method.

Also, it's worth knowing that all intermediate stream operations are lazy (See Java 8 in Action). They are the operation which returns another Stream instead of value. The terminal operation returns value or creates side-effect . So, don't worry about performance, one of the key reason for using stream is lambda is lazy evaluation which presents optimization opportunity depending upon the algorithm.


Java Program to find the first element of Stream in JDK 8

Here is our Java program to demonstrate how you can use stream utility methods like map(), flatMap() and findFirst() to filter and find out the first element from Stream in Java 8.

import java.util.ArrayList;
import java.util.List;

/*
 * Java Program to show how to find the first element
 * of Stream in Java 8. 
 */
public class Java8Demo {

    public static void main(String args[]) {

        // a list of electronic gadgets
        List<String> gadgets = new ArrayList<>();
        gadgets.add("SmartPhone");
        gadgets.add("SmartWatch");
        gadgets.add("SmartTV");
        gadgets.add("SmartDoor");
        gadgets.add("iPhone");

        // printing gadgets whose length is greater than 7
        // using pre Java 8 techniques
        for (String gadget : gadgets) {
            if (gadget.length() > 7) {
                System.out.println("Prior ot Java 8: " + gadget);
                break;
            }
        }

        // retrieving gadgets with length greater than 8
        // using lambda expression and stream methods
        // in Java 8
        String item = gadgets.stream()
                .filter(s -> s.length() > 8)
                .findFirst()
                .orElse("");

        System.out.println("In Java 8, first item: " + item);

        // you can further use peek() to see
        // what's going inside filter or other stream
        // methods. 
        String myItem = gadgets.stream()
                .peek(s -> System.out.println("processing: " + s))
                .filter(s -> s.length() > 8)
                .findFirst()
                .orElse("");
        System.out.println("result: " + myItem);
    }

}

Output:
Prior ot Java 8: SmartPhone
In Java 8, first item: SmartPhone
processing: SmartPhone
result: SmartPhone

That's all about how to find the first element in Stream in Java 8. You can use the findFist() method to get the first object. It's a terminal operation and should be the last call on stream because after that you cannot call any method on Stream. Intermediate operations are evaluated lazily.



No comments :

Post a Comment