【问题标题】:Merging 2 HashMaps in Java在 Java 中合并 2 个 HashMap
【发布时间】:2012-05-30 08:25:04
【问题描述】:

我有一个程序需要合并两个HashMap。哈希映射有一个String 的键和一个Integer 的值。合并的特殊条件是,如果键已经在字典中,Integer 需要添加到现有值中,而不是替换它。这是我到目前为止抛出NullPointerException的代码。

public void addDictionary(HashMap<String, Integer> incomingDictionary) {
        for (String key : incomingDictionary.keySet()) {
            if (totalDictionary.containsKey(key)) {
                Integer newValue = incomingDictionary.get(key) + totalDictionary.get(key);
                totalDictionary.put(key, newValue);
            } else {
                totalDictionary.put(key, incomingDictionary.get(key));
            }
        }
    }

【问题讨论】:

  • NPE 在哪一行被抛出?
  • 你初始化totalDictionary字段了吗?
  • totalDictionary 已声明但未在包装此函数的类的早期初始化为私有成员数据。 Eclipse 显示在 for 循环所在行抛出的异常。
  • 这可能意味着incomingDictionary 为空或者incomingDictionary 包含null 作为键。
  • 另外,您必须先初始化totalDictionary,然后才能使用它...否则您将获得更多的 NPE。

标签: java android dictionary hashmap


【解决方案1】:

如果你的代码不能保证incomingDictionary在到达这个方法之前会被初始化,你就得做一次空检查,没有出路

public void addDictionary(HashMap<String, Integer> incomingDictionary) {
    if (incomingDictionary == null) {
        return; // or throw runtime exception
    }
    if (totalDictionary == null) {
        return;// or throw runtime exception
    }
    if (totalDictionary.isEmpty()) {
        totalDictionary.putAll(incomingDictionary);
    } else {
        for (Entry<String, Integer> incomingIter : incomingDictionary.entrySet()) {
            String incomingKey = incomingIter.getKey();
            Integer incomingValue = incomingIter.getValue();
            Integer totalValue = totalDictionary.get(incomingKey);
            // If total dictionary contains null for the incoming key it is
            // as good as replacing it with incoming value.
            Integer sum = (totalValue == null ? 
                                            incomingValue : incomingValue == null ? 
                                                    totalValue : totalValue + incomingValue
                          );
            totalDictionary.put(incomingKey, sum);
        }
    }
}

考虑到 HashMap 允许 null 作为值,代码中另一个容易出现 NPE 的地方是

Integer newValue = incomingDictionary.get(key) + totalDictionary.get(key);

如果这两个中的任何一个为空,您将获得 NPE。

【讨论】:

  • if(totalDictionary.isEmpty()) 那么totalDictionary.putAll(incomingDictionary) else 做for循环怎么样?
  • 如果incomingDictionary 为null,那么putAll 将抛出NullPointerException
【解决方案2】:

您可能有一个字典未初始化。 这是一种解决方案:

public void addDictionary(HashMap<String, Integer> incomingDictionary) {
    if (incomingDictionary == null) {
        throw new IllegalArgumentException("incomingDictionary cannot be null.");
    }
    if (totalDictionary == null) {
        throw new IllegalArgumentException("totalDictionary cannot be null.");
        // or another solution:
        // totalDictionary = new HashMap<String, Integer>();
        // totalDictionary.putAll(incomingDictionary);
        // return;
    }

    for (Map.Entry<String, Integer> entry : incomingDictionary.entrySet()) {
        Integer oldValue = totalDictionary.get(entry.getKey());
        if (oldValue != null){
            // here entry.getValue() could be null!
            // Never put a null value in your Map, or add a test here
            Integer newValue = entry.getValue() + oldValue;
            totalDictionary.put(entry.getKey(), newValue);
        } else {
            totalDictionary.put(entry.getKey(), entry.getValue());
        }
    }
}

【讨论】:

  • 如果entry.getValue()返回null,再次NPE
  • 确实!但我认为他的责任是永远不要将null 作为地图中的值......但我会根据你的评论编辑我的帖子。
  • 如果map不包含`getValue(key)`中key的值,它可以返回null;
【解决方案3】:

考虑到totalDictionary已正确初始化,在:

Integer newValue = incomingDictionary.get(key) + totalDictionary.get(key);

totalDictionary.get(key) 无法返回 null
也许您需要在之前添加类似的内容:

if(totalDictionary.get(key) == null)
  totalDictionary.put(key, 0);

【讨论】:

    猜你喜欢
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    • 2012-01-12
    • 2018-11-11
    • 1970-01-01
    • 1970-01-01
    • 2021-11-13
    相关资源
    最近更新 更多