【问题标题】:Why does this Java code using HashMap cause NullPointerException? [closed]为什么这个使用 HashMap 的 Java 代码会导致 NullPointerException? [关闭]
【发布时间】:2021-10-14 21:12:46
【问题描述】:

这是我在解决leetcode问题954. Array of Doubled Pairs时遇到的。

这是一个存储每个值的计数的全局映射。我使用下面的这个函数来检查列表中的值(也在地图中)是否全部配对(如果地图有valuevalue * 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 0s、10052 1s 和 10003 2s),它会抛出 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 不再发生。 为什么会这样?

【问题讨论】:

标签: java nullpointerexception hashmap


【解决方案1】:

map.get() 可以返回null(如果没有找到密钥)。

如果您尝试将null 分配给原始类型int 的变量,您会得到NullPointerException(另请参见Unboxing Null-Object to primitive type results in NullPointerException, fine?)。

因此,如果您不通过map.containsKey(key) 检查该值是否存在,或者在将其转换为int 之前检查null 的结果,则会出现异常。

正如this answer 中已经正确提到的,您的修改版本在第一次修改后检查是否存在第二个键,即使两个键的值相同(0 就是这种情况)和第一次修改删除了第二次修改查找的键。

【讨论】:

  • 谢谢Hulk。但是,困扰我的是map.containsKey(key)map.containsKey(key * 2) 都满足了,但是map.get(key)返回null。
  • 感谢您的提示 - 我使用来自 vsfDawg 的答案的正确信息更新了我的答案,0 的情况在这里很重要。
【解决方案2】:

您的地图只能包含具有 Integer 类型键的 Integer 类型的对象。

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

当映射不包含特定键的对象时,它将返回 null。

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

当您尝试将 Integer-Object 拆箱为 int 值时,当 Integer-Object 为 null 时,这将引发 NullPointerException。

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

让我们在 jshell 中尝试一下。所以打开一个控制台窗口并使用 jshell:

启动 JShell

【讨论】:

  • 谢谢Tobias Otto。我会在 jshell 中试试这个。
【解决方案3】:

NullPointerException (NPE) 发生在第一种情况下,因为keykey*2key=0 时是相同的值。第二个版本的代码在第一个映射已经被删除之后测试key*2 的存在,因此它不会遇到 NPE。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 2022-10-20
  • 1970-01-01
  • 1970-01-01
  • 2011-03-16
相关资源
最近更新 更多