Filter java stream to 1 and only 1 element

In this article, we will take a look at different methods to filter a java stream to 1 and only 1 element.
So, the result will ONLY be a single element out of stream.

Method 1: findFirst()
Stream findFirst() method returns an Optional object that contains the first element in a stream.
If the stream is empty, an empty Optional is returned.  Example,

List<Integer> numbers = List.of(1, 2, 3, 4, 5);
Integer firstNumber = numbers.stream()
    .findFirst()
    .orElse(null);

In this example, we have reduced the stream to only one element, which is the first element.
Method 2: Using findAny()
findAny() returns an Optional object that contains any element from the stream. This element may be any random element from the stream and it might differ between different executions of the program.
If the stream is empty, an empty Optional is returned. Example,

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Integer anyNumber = numbers.stream()
    .findAny()
    .orElse(null);

Method 3: Using Collectors.reducing()
Collectors.reducing() is a method that can be used to reduce a stream to a single value using a specified reduction operation.
It takes an argument of type BinaryOperator, which is a functional interface. Its abstract method accepts two arguments and returns a value.
Collectors.reducing() returns an Optional object as a result of applying the reduction function to the elements in the stream. Example,

List<Integer> numbers = List.of(21, 34, 55, 4, 51);
Optional<Integer> max = numbers.
                        stream().
                        collect(Collectors.reducing(Integer::max));

Above example gets the maximum element of the stream.
Here, the operator :: is called reference operator.
It is a shorthand for Integer.max() method, which takes two arguments and hence can be supplied in place of BinaryOperator.

There is also an overloaded version of reducing() method which takes two arguments
A. Identity value.
Identity value is 1 for multiplication and 0 for addition. It is also the value, which must be returned if stream is empty.
B. Reduction function.
The identity value is the initial value of the reduction and the reduction function is used to combine the stream elements with the current reduction value.

Second argument or the reduction function is of type BinaryOperator, which is a functional interface.
Its abstract method accepts two arguments and returns a value. Example,

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Integer product = numbers.stream()
    .collect(Collectors.reducing(1, (a, b) -> a * b));

Above example of uses Collectors.reducing() to get the product of all the elements in a stream of integers.

In this example, the identity value is 1 and the reduction function is a lambda expression that multiplies two integers.
The stream is initially reduced to the identity value 1, and then the reduction function is applied to each element in the stream, multiplying the current reduction value with the next element in the stream.
The final reduction value is the product of all the elements in the stream.

Method 4: Using Collectors.collectingAndThen()
Collectors.collectingAndThen() method allows you to perform an additional operation on the result of a collector after it has been collected.
As per the java docs,

Adapts a Collector to perform an additional finishing transformation

It takes two arguments:
A. a collector, and
B. a function.
The collector is used to perform the initial collection, and the function is applied to the result of the collection.
Second argument, that is, the function is an argument of type java.util.function.Function, which is a functional interface. Example,

List<Integer> numbers = List.of(1, 2, 3, 4, 5);
Integer first = numbers.stream()
    .collect(
       Collectors.
       collectingAndThen(Collectors.toList(), list -> list.get(0))
    );

This example uses Collectors.collectingAndThen() to get the first element of a stream of integers.
First argument of collectingAndThen() is a collector, which is retrieved from Collectors.toList(). It collects the elements of the stream into a list.
The function applied to the result of the collection is a lambda expression that returns the first element of the list.

Hope the article was useful.