为什么这个 Java 使用 HashMap 的代码会导致 NullPointerException?
Why does this Java code using HashMap cause NullPointerException?
这是我在解决leetcode问题时遇到的954. Array of Doubled Pairs。
这是一张全局地图,其中存储了每个值的计数。我在下面使用这个函数来检查列表中的值(也在地图中)是否都是成对的(如果地图有 value
和 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);
}
}
对于这种情况(9945 0、10052 1 和 10003 2),它抛出 NullPointerException。这是异常消息:
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
当我将函数 isPaired
更改为以下代码时:
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 不再发生。
为什么会发生这些?
map.get()
可以returnnull
(如果找不到key)
如果您尝试将 null
分配给基本类型 int
的变量,您将得到 NullPointerException
(另请参阅 Unboxing Null-Object to primitive type results in NullPointerException, fine?)。
因此,如果您不通过 map.containsKey(key)
检查该值是否存在或在将其转换为 int
之前检查 null
的结果,则会出现异常。
正如在 中正确提到的那样,您的修改版本会在第一次修改后检查是否存在第二个键,即使两个键的值相同([= 的情况也是如此) 18=]) 并且第一次修改删除了第二次修改查找的密钥。
您的地图只能包含具有整数类型键的整数类型对象。
Map<Integer, Integer> map = new HashMap<>();
当地图不包含特定键的对象时,它将 return 为空。
map.get(key); --> will return a null-Integer
当您尝试将 Integer-Object 拆箱为 int 值时,当 Integer-Object 为 null 时,这将抛出 NullPointerException。
int value = map.get(key); // throws NullPointerException
让我们在 jshell 中试试这个。所以打开一个控制台-window 并使用 jshell:
启动 JShell
第一种情况会出现NullPointerException (NPE),因为key
和key*2
在key=0
时是相同的值。第二个版本的代码在第一个映射已被删除后测试 key*2
是否存在,因此它不会遇到 NPE。
这是我在解决leetcode问题时遇到的954. Array of Doubled Pairs。
这是一张全局地图,其中存储了每个值的计数。我在下面使用这个函数来检查列表中的值(也在地图中)是否都是成对的(如果地图有 value
和 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);
}
}
对于这种情况(9945 0、10052 1 和 10003 2),它抛出 NullPointerException。这是异常消息:
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
当我将函数 isPaired
更改为以下代码时:
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 不再发生。 为什么会发生这些?
map.get()
可以returnnull
(如果找不到key)
如果您尝试将 null
分配给基本类型 int
的变量,您将得到 NullPointerException
(另请参阅 Unboxing Null-Object to primitive type results in NullPointerException, fine?)。
因此,如果您不通过 map.containsKey(key)
检查该值是否存在或在将其转换为 int
之前检查 null
的结果,则会出现异常。
正如在
您的地图只能包含具有整数类型键的整数类型对象。
Map<Integer, Integer> map = new HashMap<>();
当地图不包含特定键的对象时,它将 return 为空。
map.get(key); --> will return a null-Integer
当您尝试将 Integer-Object 拆箱为 int 值时,当 Integer-Object 为 null 时,这将抛出 NullPointerException。
int value = map.get(key); // throws NullPointerException
让我们在 jshell 中试试这个。所以打开一个控制台-window 并使用 jshell:
第一种情况会出现NullPointerException (NPE),因为key
和key*2
在key=0
时是相同的值。第二个版本的代码在第一个映射已被删除后测试 key*2
是否存在,因此它不会遇到 NPE。