Java 8 Stream findFirst() and filter() Example

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 Stream along with filter() and findFirst() method to find out an element based upon a predicate.

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 e.g. 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 method, much like short circuit AND (&&) and OR (||) operator which will not evaluate anymore element once they found one.



How to find the first element from a Stream with 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 The Complete Java SE 8 Developer BootCamp to learn more about Stream features.

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 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 Optional return by 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 satisfy 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
How to do Map Reduce in Java 8?
How to use flatMap in Java 8?
10 examples of forEach() method in Java 8?
3 ways to read a file line by line in Java 8
10 examples of converting a List<V> to Map of <K, V> in Java 8?
Beginning Java 8 Language Features by Kishori Sharan
Top 5 Books to Learn Java 8 Better

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

No comments:

Post a Comment