Skip to content

Why list.contains(null) throwing null pointer exception?

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?

Answer

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:

  1. The List.of methods are specified as producing unmodifiable lists.

  2. Unmodifiable lists are specified to not permit null elements:

    “They disallow null elements. Attempts to create them with null elements result in NullPointerException.”

  3. The javadoc for List.contains states:

    “Throws: NullPointerException – if the specified element is null and this list does not permit null 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. But it is moot. The List design choices were made a long time ago and changing them would now would be too disruptive to contemplate. Besides, I doubt that you would convince the current Java design team that null values in collection types are a good idea.)