【问题标题】:FindBugs warning: Inefficient use of keySet iteratorFindBugs 警告:keySet 迭代器的低效使用
【发布时间】:2014-08-28 10:51:12
【问题描述】:

这是一个与 [FindBugs warning: Inefficient use of keySet iterator instead of entrySet iterator

类似的问题

但是,我正在尝试做一些不同的事情。我当前的代码在这里:

for (Double key2 : sortedPolygons.keySet()) {
    if (sortedPolygons.get(key2).getExteriorRing().equals(hole)) {
        sortedPolygons.remove(key2);
        break;
    }
}

执行链接中的解决方案之类的操作不起作用。这是所述解决方案的实现:

for(Map.Entry<Double, Polygon> entry : sortedPolygons.entrySet()) {
    if (entry.getValue().getExteriorRing().equals(hole)) {
         .....

这里的问题是我正在尝试删除该条目。没有entry.remove()。如何在没有 FindBugs 错误的情况下替换我的第一个代码块:

低效使用keySet迭代器代替entrySet迭代器 ->

此方法使用一个键访问 Map 条目的值,该键是 从 keySet 迭代器中检索。使用一个更有效 映射 entrySet 上的迭代器,避免 Map.get(key) 查找。

需要注意的是,底层结构是TreeMap,不能更改。

【问题讨论】:

    标签: java iterator sonarqube treemap findbugs


    【解决方案1】:

    我无法理解你的推理:在第一个 sn-p 中,你使用了

    sortedPolygons.remove(key2);
    

    删除一个键。没有什么能阻止你在第二个 sn-p 中做同样的事情:

    sortedPolygons.remove(entry.getKey());
    

    无论您以何种方式进行迭代,这都会导致ConcurrentModificationException,因为对于大多数集合,您无法在迭代时对其进行修改,除非使用其迭代器。

    引用the javadoc:

    该类的所有“集合视图方法”返回的集合的迭代器方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间对映射进行结构修改,除了通过迭代器自己的remove方法,迭代器会抛出ConcurrentModificationException。

    所以代码应该是:

    for (Iterator<Map.Entry<Double, Polygon>> it = sortedPolygons.entrySet().iterator(); it.hasNext(); ) {
        Map.Entry<Double, Polygon> entry = it.next();
        if (entry.getValue().getExteriorRing().equals(hole)) {
            it.remove();
            // if you want to exit the loop as soon as you found a match:
            break;
        }
    }
    

    【讨论】:

    • 注意:实际上并不需要密钥(见我的回答)
    • @PeterLawrey:同意。 +1 对您的回答。我将保留我的答案,以向 OP 展示如何迭代条目,以防他将来需要密钥。
    • 在remove 之后,OP 是breaking。但是 +1 用于使用 Iterator。
    • @BoristheSpider:现在我明白了。这就是他没有得到 ConcurrentModificationException 的原因。虽然非常脆弱。我仍然会使用迭代器,它在删除方面也更有效。
    • 值得注意的是,您不需要为此使用entrySet();每个集合视图都支持删除。所以在这里,你可以使用for(Iterator&lt;Polygon&gt; it = sortedPolygons.values() .iterator(); it.hasNext(); ) if(it.next().getExteriorRing().equals(hole)) { it.remove(); break; },如果不需要短路,Java 8 的sortedPolygons.values() .removeIf(poly -&gt; poly.getExteriorRing().equals(hole)); 会更流畅。
    【解决方案2】:

    您如何按照建议使用 entrySet() 迭代器。

    for(Iterator<Map.Entry<Double, Ploygon>> iter = sortedPolygons.entrySet().iterator(); 
             iter.hasNext();) {
        Map.Entry<Double, Ploygon> entry = iter.next();
    
        if (condition)
            iter.remove();
    }
    

    但是您不需要密钥,因此您可以迭代值

    for(Iterator<Ploygon> iter = sortedPolygons.values().iterator(); 
             iter.hasNext();) {
        Ploygon ploygon = iter.next();
    
        if (condition)
            iter.remove();
    }
    

    【讨论】:

    • 啊。我知道了。该键仅用于迭代值。所以只需迭代值。
    • +1 提醒我您可以使用值迭代器删除完整条目。
    猜你喜欢
    • 2012-09-20
    • 2021-10-10
    • 2013-10-30
    • 2015-12-23
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多