I have List<Long> countriesList
which contains Long
values which are country ids.
Now I am iterating over some List<UserRequests>
list by using streams
.
userRequests.stream().
forEach(userRequest->
{
UserData=userRepository.findById(userRequest.getId()); //fine
if (CollectionUtils.isNotEmpty(countriesList) && countriesList.contains(userRequest.getCountryId()))//getting NPE here
{
//do some operation
}
});
I tried to debug by evaluating individual statements.
I have made sure countriesList
have some data
First part CollectionUtils.isNotEmpty(countriesList)
is returning true
.
userRequest
is also not null but userRequest.getCountryId()
is null.
And when I evaluated countriesList.contains(userRequest.getCountryId())
, I am getting Null pointer exception
here. why not false
?
I am confused what wrong am I doing.
Is default list.contains(null)
behaviour is like that only or is it because I am calling it within stream()
?
Just for simplification I have created simple list and compared with null
.
class Test {
public static void main(String[] args) {
List<Long> longList = List.of(1L, 2L, 3L);
System.out.println("Comparing long list with null::" + longList.contains(null));
}
}
This is the exception I am getting:
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:222)
at java.base/java.util.ImmutableCollections$AbstractImmutableList.indexOf(ImmutableCollections.java:166)
at java.base/java.util.ImmutableCollections$AbstractImmutableList.contains(ImmutableCollections.java:197)
at com.test.Test.main(Test.java:26)
But If I do:
List<Long> longList = new ArrayList<>();
longList.add(1L);
System.out.println("Comparing long list with null::" + longList.contains(null));
Why it is printing false
? Why no NullPointerException
here?
Why
list.contains(null)
throwing null pointer exception?
Because this is what the specs say can happen.
The specific reasoning for the List.of(...)
case is as follows:
The List.of
methods are specified as producing unmodifiable lists.
Unmodifiable lists are specified to not permit null
elements:
"They disallow null elements. Attempts to create them with
null
elements result inNullPointerException
."
The javadoc for List.contains
states:
"Throws:
NullPointerException
- if the specified element isnull
and this list does not permitnull
elements.
In other words, what you are seeing is specified behavior ... and not a result of an incorrect or capricious implementation.
For the case where you are searching countryList
... it will depend on the actual List
implementation class. But there is a clear expectation in the List
spec for contains
that some kinds of list may throw an NPE if you try to search for null
.
(Whether that is a "poor design choice" or not is a matter of opinion. I don't think so. But either way, this is a moot point. The List
design choices were made a long time ago and changing them would now would be too disruptive to contemplate. And I doubt that you would convince the current Java design team that allowing null
values in collection types is a good idea.)
Note: the same restriction applies to immutable sets; e.g. as created using Set.of(...)
calls.