1. Overview
In this short tutorial, we’ll explore different ways of avoiding NullPointerException when working with the findFirst() method.
First, we’ll explain what causes the method to fail with NullPointerException. Then, we’ll demonstrate how to reproduce and fix the exception using practical examples.
2. Explaining the Problem
In short, a NullPointerException is thrown to signal that we’re doing some operation using null where an object is required.
Typically, we use findFirst() to return an Optional instance holding the first element of a given stream. However, according to the documentation, the method throws NullPointerException if the first returned element is null.
So, the main question here is how to avoid the NullPointerException exception when the first element of our stream is null. Before diving deep and answering our question, let’s reproduce the exception.
3. Reproducing the NullPointerException
For instance, let’s assume we have a list of String objects:
List<String> inputs = Arrays.asList(null, "foo", "bar");
Now, let’s try to get the first element of our list using the findFirst() method:
@Test(expected = NullPointerException.class)
public void givenStream_whenCallingFindFirst_thenThrowNullPointerException() {
Optional<String> firstElement = inputs.stream()
.findFirst();
}
As we can see, the test case fails with NullPointerException because the first selected element of our list is null.
The Optional API states that it’s the caller’s responsibility to ensure that the value is not null because it doesn’t provide any way to distinguish between “the value is present but set to null” and “the value is not present”. This is why the documentation prohibits the scenario where null is returned when using findFirst().
4. Avoiding the Exception
The easiest way to avoid NullPointerException in this case is to filter the stream before calling the findFirst() method.
So, let’s see how we can do this in practice:
@Test
public void givenStream_whenUsingFilterBeforeFindFirst_thenCorrect() {
Optional<String> firstNotNullElement = inputs.stream()
.filter(Objects::nonNull)
.findFirst();
assertTrue(firstNotNullElement.isPresent());
}
Here, we used the Objects#nonNull method to filter only objects that are not null. That way, we ensure the selected first element is not null. As a result, we avoid NullPointerException.
Another option would be to use the Optional#ofNullable method before calling the findFirst() method.
This method returns an Optional instance with the specified value if it’s not null. Otherwise, it returns an empty Optional.
So, let’s see it in action:
@Test
public void givenStream_whenUsingOfNullableBeforeFindFirst_thenCorrect() {
Optional<String> firstElement = inputs.stream()
.map(Optional::ofNullable)
.findFirst()
.flatMap(Function.identity());
assertTrue(firstElement.isEmpty());
}
As shown above, we map each element into an Optional object that accepts null with the help of the ofNullable() method. Then, we get the first mapped element using findFirst().
The returned element denotes an Optional of an Optional since findFirst() returns an Optional. This is why we used flapMap() to flatten the nested Optional.
Please note that Function#identity always returns its input argument. In our case, the method returns null because it’s the first element of our list.
5. Conclusion
In this short article, we explained how to avoid NullPointerException when working with the findFirst() method.
Along the way, we showcased how to reproduce and solve the exception using practical examples.
As always, the full source code of the examples is available over on GitHub.