In this article, we will discuss Stream’s findFirst() and findAny() methods in details with examples along with their differences
1. Stream findFirst() method :
- This Stream method is a terminal operation which returns Optional instance describing first element of the given Stream
- If provided Stream has encounter-order then first element is returned (encounter-order depends on the source or intermediate operations)
- But if provided Stream has no-encounter-order then any element may be returned
- If provided Stream is empty or intermediate operation‘s result is empty then empty Optional is returned i.e.; Optional.empty()
- Note: Above behavior is true for both sequential and parallel streams
- It is a short-circuiting terminal operation, as Stream pipeline ends when first or any one element is returned and no further evaluation/processing happens in the Stream (we can debug this behavior using Stream’s peek() method)
- Method signature :- Optional<T> findFirst()
2. Stream findFirst() method examples :
2.1 To find first element from Integer list
- A list contains integer numbers from 1 to 10
- First, we are finding first element from Sequential Stream which returns 1, as it is the first element in the provided List
- Second, we are again finding first element but this time from Parallel Stream which also returns 1
- Third, we are filtering Even numbers from Sequential Stream and finding first element which returns 2
- Note: List stores elements in insertion-order
package net.bench.resources.stream.findfirst.example;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class StreamFindFirstMethodForIntegers {
public static void main(String[] args) {
// list of integer numbers
List<Integer> numbers = Arrays.asList(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
);
// 1. Sequential - findFirst() from list of integers
Optional<Integer> result1 = numbers // data-source
.stream() // get sequential stream
.findFirst(); // find first
// 1.1 print Sequential result
if(result1.isPresent()) {
Integer firstNum = result1.get();
System.out.println("1. Sequential findFirst() result is = "
+ firstNum);
}
else {
System.out.println("No value is pressnt");
}
// 2. Parallel - findFirst() from list of integers
numbers // data-source
.parallelStream() // get parallel stream
.findFirst() // find first
.ifPresent(num ->
System.out.println("\n2. Parallel findFirst() result is = "
+ num)); // print
// 3. filtering and findFirst()
Optional<Integer> result3 = numbers // data-source
.stream() // get sequential stream
.filter(num -> num % 2 == 0) // filter Even numbers
.findFirst(); // find first
// 3.1 print to console
result3.ifPresent(num ->
System.out.println("\n3. filter Even numbers & findFirst() result is = "
+ num));
}
}
Output:
1. Sequential findFirst() result is = 1
2. Parallel findFirst() result is = 1
3. filter Even numbers & findFirst() result is = 2
2.2 To find first element from list of String elements
- A list contains 5 String elements
- First, we are finding first String element from Sequential Stream which returns Putin, as it is the first element in the provided List
- Second, we are again finding first String element but this time from Parallel Stream which also returns Putin
- Third, we are filtering names starting with ‘M’ from Sequential Stream and finding first element which returns Manmohan
- Finally, we are trying to find first String element for names starting with ‘A‘ and String list doesn’t contains any match for this name, therefore empty Optional is returned i.e.; Optional.empty()
- Note: List stores elements in insertion-order
package net.bench.resources.stream.findfirst.example;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class StreamFindFirstMethodForString {
public static void main(String[] args) {
// list of Strings
List<String> names = Arrays.asList(
"Putin",
"Biden",
"Manmohan",
"Modi",
"Jack"
);
// 1. Sequential - findFirst() from list of Strings
Optional<String> result1 = names // data-source
.stream() // get sequential stream
.findFirst(); // find first
// 1.1 print to console
result1.ifPresent(str -> System.out.println(
"1. Sequential findFirst() String result is = "
+ str));
// 2. Parallel - findFirst() from list of Strings
Optional<String> result2 = names // data-source
.parallelStream() // get parallel stream
.findFirst(); // find first
// 2.1 print to console
result2.ifPresent(str -> System.out.println(
"\n2. Parallel findFirst() String result is = "
+ str));
// 3. filtering and findFirst()
Optional<String> result3 = names // data-source
.stream() // get sequential stream
.filter(str -> str.startsWith("M")) // filter
.findFirst(); // find first
// 3.1 print to console
result3.ifPresent(str -> System.out.println(
"\n3. filter name starting with 'M' & findFirst() result is = "
+ str));
// 4. empty Optional and findFirst()
Optional<String> result4 = names // data-source
.stream() // get sequential stream
.filter(str -> str.startsWith("A")) // filter
.findFirst(); // find first
// 4.1 print to console
System.out.println("\n4. names starting with 'A' = " + result4);
}
}
Output:
1. Sequential findFirst() String result is = Putin
2. Parallel findFirst() String result is = Putin
3. filter name starting with 'M' & findFirst() result is = Manmohan
4. names starting with 'A' = Optional.empty
3. Stream findAny() method :
- This Stream method is a terminal operation which returns Optional instance describing any element from the given Stream
- If provided Stream has encounter-order then most of the times first element is returned but this behavior isn’t guaranteed
- For Stream with no-encounter-order, any element may be returned
- The behavior of this operation is explicitly nondeterministic, as it is free to select any element in the stream. For stable result, use findFirst() method as explained in above section
- If provided Stream is empty or intermediate operation‘s result is empty then empty Optional is returned i.e.; Optional.empty()
- This method is introduced for maximal performance in parallel operations
- Note: Above behavior is true for both sequential and parallel streams
- It is a short-circuiting terminal operation, as Stream pipeline ends when any element is returned and no further evaluation/processing happens in the Stream (we can debug this behavior using Stream’s peek() method)
- Method signature :- Optional<T> findAny()
4. Stream findAny() method examples :
4.1 To find any element from Integer list
- A list contains integer numbers from 1 to 10
- First, we are finding any element from Sequential Stream which returns 1
- Second, we are again finding any element but this time from Parallel Stream which returns 7 (this is difference from the result of sequential stream)
- Third, we are filtering Even numbers from Sequential Stream and finding any element which returns 2
- Note: List stores elements in insertion-order
package net.bench.resources.stream.findfirst.example;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class StreamFindAnyMethodForIntegers {
public static void main(String[] args) {
// list of integer numbers
List<Integer> numbers = Arrays.asList(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
);
// 1. Sequential - findAny() from list of integers
Optional<Integer> result1 = numbers // data-source
.stream() // get sequential stream
.findAny(); // find any element
// 1.1 print Sequential result
if(result1.isPresent()) {
Integer firstNum = result1.get();
System.out.println("1. Sequential findAny() result is = "
+ firstNum);
}
else {
System.out.println("No value is pressnt");
}
// 2. Parallel - findAny() from list of integers
numbers // data-source
.parallelStream() // get parallel stream
.findAny() // find any element
.ifPresent(num ->
System.out.println("\n2. Parallel findAny() result is = "
+ num)); // print
// 3. filtering and findFirst()
Optional<Integer> result3 = numbers // data-source
.stream() // get sequential stream
.filter(num -> num % 2 == 0) // filter Even numbers
.findAny(); // find any element
// 3.1 print to console
result3.ifPresent(num ->
System.out.println("\n3. filter Even numbers & findAny() result is = "
+ num));
}
}
Output:
1. Sequential findAny() result is = 1
2. Parallel findAny() result is = 7
3. filter Even numbers & findAny() result is = 2
4.2 To find any element from list of String elements
- A list contains 5 String elements
- First, we are finding any String element from Sequential Stream which returns Putin
- Second, we are again finding any String element but this time from Parallel Stream which returns Manmohan
- Third, we are filtering names starting with ‘M’ from Sequential Stream and finding any element which returns Manmohan
- Finally, we are trying to find any String element for names starting with ‘A‘ and String list doesn’t contains any match for this name, therefore empty Optional is returned i.e.; Optional.empty()
- Note: List stores elements in insertion-order
package net.bench.resources.stream.findfirst.example;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class StreamFindAnyMethodForString {
public static void main(String[] args) {
// list of Strings
List<String> names = Arrays.asList(
"Putin",
"Biden",
"Manmohan",
"Modi",
"Jack"
);
// 1. Sequential - findAny() from list of Strings
Optional<String> result1 = names // data-source
.stream() // get sequential stream
.findAny(); // find any element
// 1.1 print to console
result1.ifPresent(str -> System.out.println(
"1. Sequential findAny() String result is = "
+ str));
// 2. Parallel - findAny() from list of Strings
Optional<String> result2 = names // data-source
.parallelStream() // get parallel stream
.findAny(); // find any element
// 2.1 print to console
result2.ifPresent(str -> System.out.println(
"\n2. Parallel findAny() String result is = "
+ str));
// 3. filtering and findFirst()
Optional<String> result3 = names // data-source
.stream() // get sequential stream
.filter(str -> str.startsWith("M")) // filter
.findAny(); // find any element
// 3.1 print to console
result3.ifPresent(str -> System.out.println(
"\n3. filter name starting with 'M' & findAny() result is = "
+ str));
// 4. empty Optional and findAny()
Optional<String> result4 = names // data-source
.stream() // get sequential stream
.filter(str -> str.startsWith("A")) // filter
.findAny(); // find any element
// 4.1 print to console
System.out.println("\n4. names starting with 'A' = " + result4);
}
}
Output:
1. Sequential findAny() String result is = Putin
2. Parallel findAny() String result is = Manmohan
3. filter name starting with 'M' & findAny() result is = Manmohan
4. names starting with 'A' = Optional.empty
References:
- https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
- https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html
- https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html
Happy Coding !!
Happy Learning !!