-1

This is what I encountered solving leetcode problem 954. Array of Doubled Pairs.

Here's a global map which stores the count on each value. I use this function below to check if the values in the list (which is also in the map) are all paired (if the map has value and value * 2).

    Map<Integer, Integer> map;
    
    private boolean isPaired( List<Integer> list) {
         for(int key : list) {
            if (map.containsKey(key)) {
                if (map.containsKey(key * 2)) {
                    updateMap(key);
                    updateMap(key * 2);
                } else {
                    return false;
                }
            }
        }
        return true;
    }
    
    private void updateMap(int key) {
        int value = map.get(key);
        if (value - 1 == 0) {
            map.remove(key); 
        } else {
            map.put(key , value - 1); 
        }
    }

with the case (9945 0s, 10052 1s and 10003 2s), it throws NullPointerException. Here's the exception message:

java.lang.NullPointerException
  at line 54, Solution.updateMap
  at line 44, Solution.isPaired
  at line 26, Solution.canReorderDoubled
  at line 54, __DriverSolution__.__helper__
  at line 84, __Driver__.main

And as I changed the function isPaired into the code below:

 private boolean isPaired(List<Integer> list) {
         for(int key : list) {
            if (map.containsKey(key)) {
                updateMap(key);
                if (map.containsKey(key * 2)) {
                    updateMap(key * 2);
                } else {
                    return false;
                }
            }
        }
        return true;
    }

NullPointerException doesn't occur anymore. Why do these happen?

3 Answers3

1

The NullPointerException (NPE) occurs in the first case because key and key*2 are the same value when key=0. The second version of the code tests for the presence of key*2 after the first mapping has already been removed so it doesn't encounter the NPE.

vsfDawg
  • 1,425
  • 1
  • 9
  • 12
0

map.get() can return null (if the key is not found).

If you try to assign null to a variable of primitive type int, you get a NullPointerException (see also Unboxing Null-Object to primitive type results in NullPointerException, fine?).

So, if you don't check if the value exists via map.containsKey(key) or check the result for null before converting it to int, you get an exception.

As already mentioned correctly in this answer, your modified version checks for existence of the second key after the first modification, and this works even if both keys are the same value (this is the case for 0) and the first modification removes the key the second modification looks for.

Hulk
  • 6,399
  • 1
  • 30
  • 52
  • Thank you [Hulk](https://stackoverflow.com/users/2513200/hulk). However, what bothers me is that ```map.containsKey(key)``` and ```map.containsKey(key * 2) ``` are both met, but the map.get(key) returned null. – benkyouLamb663 Aug 11 '21 at 13:03
  • Thanks for the hint - I updated my answer with the correct information from vsfDawg's answer that the case of `0` is important here. – Hulk Aug 11 '21 at 13:40
0

Your map can only contain objects of type Integer with keys of type Integer.

Map<Integer, Integer> map = new HashMap<>();

When the map does not contain an object for a specific key it will return null.

map.get(key); --> will return a null-Integer

When you try to unbox a Integer-Object to an int-value this will throw NullPointerException, when the Integer-Object is null.

int value = map.get(key); // throws NullPointerException

Let´s try this in jshell. So open a console-window and start JShell with jshell:enter image description here

Tobias Otto
  • 1,634
  • 13
  • 20