Java 8 – Stream findFirst() v/s findAny() methods

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:

Happy Coding !!
Happy Learning !!

Java 8 - Filter null and empty values from a Stream
Java 8 - Stream allMatch() method with examples