Reputation: 259
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?
Upvotes: 2
Views: 14523
Reputation: 719376
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.
Upvotes: 13
Reputation: 31
If You want a nullable list then just use Arrays.asList
instead. Then contains(null)
won't throw NullPointerException
.
Upvotes: 2
Reputation: 31
From the API Documentation of java.util.List:
Some list implementations have restrictions on the elements that they may contain. For example, some implementations prohibit null elements, and some have restrictions on the types of their elements. Attempting to add an ineligible element throws an unchecked exception, typically NullPointerException or ClassCastException. Attempting to query the presence of an ineligible element may throw an exception, or it may simply return false; some implementations will exhibit the former behavior and some will exhibit the latter. More generally, attempting an operation on an ineligible element whose completion would not result in the insertion of an ineligible element into the list may throw an exception or it may succeed, at the option of the implementation. Such exceptions are marked as "optional" in the specification for this interface.
boolean contains(Object o)
Returns
true
if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that Objects.equals(o, e).Specified by:
contains in interface Collection
Parameters:
o - element whose presence in this list is to be tested
Returns:
true if this list contains the specified element
Throws:
ClassCastException - if the type of the specified element is incompatible with this list (optional)
NullPointerException - if the specified element is null and this list does not permit null elements (optional)
It seems that your countriesList
is of a List type that doesn't accept null
elements, such as those produced by List.of
or List.copyOf
Upvotes: 3