Saturday, July 10, 2021

How to find the first element in 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 is 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 allows you to apply several useful methods defined in the java.util.Stream class like filter(), map(), flatMap() etc.

One of the important things 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 opportunities for optimization depending upon the size of the original list. In this article, I'll show you a couple of examples of the findFirst() method with Predicate to show the true power of Stream in Java 8.

You can also join these Functional Programming and Stream APIcourses for some really good examples and explanations. The instructor of these online courses has done a fabulous job of 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 a 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 that is lazy and only evaluated when you call a terminal method like the forEach() method or findFirst() method as in this case.

This means the filter() will not scan the whole list but only the first few elements until it got the one whose length is greater than 10. You can verify this by using the peek() method which prints the 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 satisfies the findFirst() method.

Also, it's worth knowing that all intermediate stream operations are lazy (See Java 8 in Action). They are the operation that returns another Stream instead of value. The terminal operation returns a value or creates a side-effect. So, don't worry about performance, one of the key reason for using stream is lambda is a 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.


Related Java 8 Tutorials
If you are interested in learning more about the new features of Java 8, here are my earlier articles covering some of the important concepts of Java 8:
  • 20 Examples of Date and Time in Java 8 (tutorial)
  • How to use Stream class in Java 8 (tutorial)
  • How to use filter() method in Java 8 (tutorial)
  • How to use forEach() method in Java 8 (example)
  • How to join String in Java 8 (example)
  • How to convert List to Map in Java 8 (solution)
  • How to use peek() method in Java 8 (example)
  • 5 Books to Learn Java 8 from Scratch (books)
  • How to convert the stream to array in Java 8 (tutorial)
  • Java 8 Certification FAQ (guide)
  • Java 8 Mock Exams and Practice Test (test)

Thanks for reading this article so far. If you like this article then please share it with your friends and colleagues. If you have any questions, doubts, or feedback then please drop a comment and I'll try to answer your question.

No comments :

Post a Comment