【问题标题】:call to map.get inside For/in loop throws nullpointerexception while iterator doesn't在 For/in 循环中调用 map.get 会抛出 nullpointerexception 而迭代器不会
【发布时间】:2012-11-18 12:44:43
【问题描述】:

我为此花了几个小时的时间,但需要继续并找到一个丑陋的解决方法,但我很乐意清理我的代码,问题是:

public static void function1(Map<String, Float> map)
{
    for(String key : map.keySet()) {
        Float val = map.get(key);
        // val is null here, throws NPE as soon as we try to use it
    }
}

public static void function2(Map<String, Float> map)
{
    Iterator<Entry<String, Float>> it = map.entrySet().iterator();
    while(it.hasNext()) {
        Entry<String, Float> entry = it.next();
        String key = entry.getKey();
        Float val = entry.getValue();
        // do something with key & val, works fine
    }
}

参数Map&lt;String, Float&gt; map 当然已经正确初始化并且不包含任何空值。

附带说明,如果我将参数更改为 Map map 并仅使用字符串对,则 function1 可以正常工作。我的目标是只有 1 个带有泛型 Map&lt;? extends Object, ? extends Object&gt; map 的函数,我可以将其用于两种类型的地图。

任何建议表示赞赏,谢谢! 托马斯


编辑:我添加了一些非常基本的内省以使该函数与泛型一起使用。我可以确认在使用键集时我仍然得到空值,而我遵循下面的建议来使用条目集。下面是我的代码(第一个函数工作正常,而第二个函数返回空元素。

// yeah, it's aweful, but it works.
public static JsonNode map2JSON(Map<? extends Object, ? extends Object> map)
{
    ObjectNode dummyObject = Json.newObject();
    ArrayNode result = dummyObject.putArray("dummyKey");
    for(Entry<?, ?> entry : map.entrySet()) {
        ObjectNode mapElementNode = result.addObject();
        if("java.lang.String".equalsIgnoreCase(entry.getKey().getClass().getName())) {
            String key = (String)entry.getKey();
            if("java.lang.Float".equalsIgnoreCase(entry.getValue().getClass().getName())) {
                Float val = (Float)entry.getValue();
                mapElementNode.put(key, val);
            } else if("java.lang.String".equalsIgnoreCase(entry.getValue().getClass().getName())) {
                String val = (String)entry.getValue();
                mapElementNode.put(key, val);
            }
        }
    }
    return result;
}

// result here contains valid keys (the string part) and null values (the float part)
@Deprecated
public static JsonNode mapSF2JSON(Map<String, Float> map)
{
    ObjectNode dummyObject = Json.newObject();
    ArrayNode result = dummyObject.putArray("dummyKey");
    for(String key : map.keySet()) {
        ObjectNode mapElementNode = result.addObject();
        mapElementNode.put(key, map.get(key));
    }
    return result;
}

【问题讨论】:

  • 创建地图时如何插入字符串?你能把那个sn-p贴出来吗?
  • 显示地图数据,如果能显示完整代码......
  • 添加一个 sn-p 来回复下面的答案。我确定这些字符串不为空,因为如果我调用 map.toString() 我可以正常读取整个内容

标签: java generics iterator


【解决方案1】:

您可能在映射中插入了 NULL 键字符串。这在使用 HashMap 时是可能的。 尽量避免添加 NULL 键。此外,您可以使用 TreeMap。

顺便说一句,迭代入口集也不错,你可以清理你的代码 通过在 function2 中使用 foreach,就像在 function1 中所做的那样:

这看起来像:

for(Entry<String, Float> entry : map.entrySet()) {
    Float val = entry.getValue();
}

虽然没有必要清理function2。 但是您应该找到将 NULL 键插入地图的位置。

【讨论】:

  • 嘿,感谢您的回答,但我 100% 确定密钥不为空。如果我用 map.toString() 打印整个地图,它工作正常,我可以看到内容。在显示我如何创建地图的 sn-p 下方发布。
  • 我记得 Sun 实现的 map.toString() 使用与您的 function2(条目集)相同的方法。然后显然您的地图中有一个 NULL 值,这是允许的。在function1中,您可以添加一行 System.out.println("key=" + key + ", value=" + value);然后你会看到导致空值的键
  • 嘿,我的地图中没有 NULL 值,我发誓! :) 请阅读我上面的编辑以及部分解决的附加代码
【解决方案2】:

function1 使用 foreach 循环,当 map 为 null 时会抛出 NullPointerException。 在使用 foreach 迭代之前,您应该检查地图是否为空

进一步你应该重写丑陋的

if("java.lang.String".equalsIgnoreCase(entry.getKey().getClass().getName())) {

 if (entry.getKey().getClass() == String.class) {

【讨论】:

  • 我喜欢丑陋的修正,谢谢!不,地图不为空(如果您阅读我上面的代码,在编辑下方,第一个函数工作正常,第二个函数为空,并且它们都使用相同的数据集)
  • 在您的代码中,我看不到任何实例化地图的地方。哪个代码创建了地图?但更重要的是:哪个类是地图?这是 TreeMap 或 HashMap 还是自酿或第三方实现的地图? (将 System.out.println(map.getClass()) 作为第一行。在我建议添加 System.out.println("key=" + key + ", value=" + value); 之前的评论中,请执行在 function1 或 mapSF2JSON 中查看导致 NullPointerException 的原因。此外,您可以发布异常的完整堆栈跟踪。如果您发现一些有用的答案,请使用箭头按钮投票
  • 嘿,感谢您的评论。 map 是一个树形图,使用接受比较器作为参数的构造函数创建,然后输入来自带有 putall 的 hashmap 的内容,没有一个键为空,我肯定知道。在这个阶段很难追溯到我遇到异常的状态,但是您可以看到上面已弃用的函数给出了 null 值,我不需要运行任何引发异常的东西。
  • 你隐藏了很多信息,但现在有一点很明显:
  • 您隐藏了很多信息,但现在有一点很明显:谁编写了比较器?和 hashCode() 函数。如果它们是由 Sun 编写的,它们将起作用。如果是自己写的比较器,很可能无法满足“equals”的约定:要写一个正确实现equals的类并不容易,和hashcode()必须一起工作。我记得我工作中的一位同事也遇到了类似的问题,他说,在 java 中有一个错误,但这是他的 equals、compare、hashcode() 中的一个错误。有关该主题的更多信息,请参阅 sun docu for equals
猜你喜欢
  • 2021-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-17
  • 2018-06-14
  • 1970-01-01
  • 2019-10-01
  • 1970-01-01
相关资源
最近更新 更多