Tuesday, August 31, 2021

Java 8 Stream filter() + findFirst Example Tutorial

Suppose, you have a list of prime numbers and you need to find the first prime number which is greater than a given number? How do you find it? Don't tell that you will loop through the list and check each element and return the first element which is greater than the given number. Well, that's right but that's not what you should do in Java 8. That's good for Java 7 or earlier version but Java 8 offers you many better alternatives and one of them is Stream. You can use the Stream class along with filter() and findFirst() methods to find out an element based upon a Predicate, a functional interface for defining a condition which returns a boolean.

The java.util.stream.Stream class provides a couple of find methods to search elements in Stream, findFirst() and findAny().

As the name suggests, the findFirst method returns the first element from the Stream, wrapped in an Optional, but only if the Stream maintains an order like a Stream generated from an ArrayList or LinkedHashMap which keeps elements in order.

If Stream doesn't maintain order then any element will be returning and this is what the findAny() method does. It returns an element from Stream.

That's why it's not guaranteed to receive the same element if you call this method again.

Both findFirst() and findAny() are short-circuit methods, much like short circuit AND (&&) and OR (||) operators which will not evaluate any more elements once they found one. If you are not familiar with what is a short circuit operation in Java, I suggest you go through the Complete Java Masterclass course on Udemy, one of the most comprehensive courses on Java.



How to find the first element from a Stream with a filter

Now, let's come back to the task at hand. As the problem statement says, we have a list of prime numbers in the increasing order e.g. 2, 3, 5, 7, 11, 13 and we need to find the first prime number which is greater than 5 i.e. our code should return 7.

In order to achieve that we'll first get the Stream from the List and then call the filter() method with the predicate number > 7, after that we'll call the findFirst() method. This will give us the result.

If you remember, filter() is an intermediate method which means after applying a filter, you can still call other methods on stream. It's also lazy which means it will not do anything until you call a terminal method like findFirst(). You can further see Learn Java Functional Programming with Lambdas and Stream course by Ranga Karnam to learn more about Stream features.

Java 8 Stream filter() + findFirst Example




Java 8 Stream filter + findFirst Example

Here is the code to find the first element from a List in Java 8 after applying a predicate:

import java.util.Arrays;
import java.util.List;

/**
* 
* A simple example find the first element from
* List based upon condition. 
*
*/
public class Hello {

  public static void main(String args[]) {

    List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13);

    int primeGreaterThanFive = primes.stream()
                  .peek(num -> System.out.println("will filter " + num))
                  .filter(x -> x > 5)
                  .findFirst()
                  .get();

     System.out.println(primeGreaterThanFive);
   }
} 

Output:
will filter 2
will filter 3
will filter 5
will filter 7
7

The code is simple, except for the peek() and get() method. I have used peek() to demonstrate that filter will not do anything until you call the findFirst() method which is a terminal operation.

Since filter() is lazy it will only process the element needed to satisfy the criterion by findFirst() and that's why all elements will not be required to process.

You can see that only 2, 3, 5, and 7 are processed to return the result. It has not touched 11 and 13.

If you change the condition to return prime which is greater than 3, then only 2, 3, and 5 will be touched. This provides a big performance boost if you are dealing with a large list e.g. something with 1 million numbers or Strings.

The get() method is used to retrieve a value from the Optional return by the findFrst() method. If you want you can also use the OrElse() method to define a default value just in case Optional is empty.

Btw, this is an extremely common code if you have started coding in Java because most of my Java 8 refactoring is replacing the loop with a functional equivalent. If you are also refactoring your code to take advantage of Java 8, I suggest you check out Heinz Kabutz's Refactoring to Java 8 Streams and Lambdas course which provides many tips with the explanation to take full advantage of Java 8 features.

Java 8 Stream findFirst() and filter() Example


That's all about how to find the first element from a List or Stream in Java 8 which satisfies a condition.  As you can see that we can specify the condition using a Predicate, which is nothing but a Functional interface with just one method test(), which returns a boolean. You can use it along with methods like the filter to perform several interesting jobs in Java 8.

Btw, if you are just starting with Java 8 then The Complete Java SE 8 Developer BootCamp course on Udemy is a nice place to start with. It nicely covers all the Java 8 topics and also helps you to prepare for OCAJP 8.


Other Java 8  Lambda and Stream Tutorials You may like

Thanks for reading this tutorial so far. If you like this Java 8 Stream tutorial then please share it with your friends and colleagues. If you have any questions or feedback then please drop a note.

P. S. - If you are keen to learn Java 8 Functional programming but looking for a free online training course to start with then you can also check out this Java 8 Functional Programming: Lambda Expressions Quickly course on Udemy. It's completely free and you just need a Udemy account to join this course. 

No comments:

Post a Comment

Feel free to comment, ask questions if you have any doubt.