【问题标题】:Java: What is the advantage of using HashMap iterator over ConcurrentHashMap?Java:使用 HashMap 迭代器优于 ConcurrentHashMap 有什么优势?
【发布时间】:2022-01-21 04:36:01
【问题描述】:

我有一个单线程程序,它使用 Map 在迭代时一个一个地删除项目。我已经读过这里可以使用迭代器来避免ConcurrentModificationException,但为什么不使用 ConcurrentHashMap 来代替它似乎更干净?

我的代码:

private final Map<Integer, Row> rowMap;


.....

private void shutDown() {

  for (Integer rowNumber : rowMap.keySet()) {
    deleteRow(rowNumber)
  }
}

....

对于我的场景,使用迭代器意味着将其声明为 final,因此 closeRow() 和 deleteRow() 方法可以访问它以将其删除。此外,iterator.remove() 方法不会返回要删除的项目的值,这在我的情况下是必需的。

我的问题是,最有效的方法是什么,它不会抛出 ConcurrentModificationException?是使用迭代器还是将 rowMap 设为 ConcurrentHashMap?

【问题讨论】:

标签: java hashmap iterator concurrenthashmap


【解决方案1】:

只有在线程之间共享ConcurrentHashMap 时才使用它。

在单线程中,在使用迭代器时修改对象时抛出CurrentModificationException

有两种方法可以从集合中删除元素,例如列表和地图。一种是在集合上调用 remove。另一种是使用迭代器。但它们不能一起使用。如果你使用集合对象的 remove 方法删除一个元素,它会使迭代器的状态无效。

List<Integer> list = new ArrayList(List.of(1,2,3,4,5));
Iterator<Integer> it = list.iterator();
list.remove(0);
        
while(it.hasNext()){
  System.out.print(it.next());
}

这是一个例外:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
    at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
    at Main.main(Main.java:15)

【讨论】:

    【解决方案2】:

    这是一个相当简单的迭代器模式。

    Iterator<Map.Entry<Integer,Row>> it = rowMap.entrySet().iterator();
    while (it.hasNext()) {
       Map.Entry<Integer,Row> ent = it.next();
       Integer key = ent.getKey(); 
       Row row = ent.getValue(); // before the remove
       it.remove();
       // ... do what you want with key and row;
    }
    

    因此,我们使用显式迭代器对地图进行迭代,这允许我们在迭代期间使用迭代器的remove 方法。我们正在迭代映射的“入口集”视图,这允许我们从单个迭代器中检索键和值。

    Documentation link

    公共集> entrySet()

    返回此映射中包含的映射的 Set 视图。套装是 由地图支持,因此对地图的更改会反映在集合中,并且 反之亦然。如果在对集合进行迭代时修改了地图 进行中(除非通过迭代器自己的删除操作,或 通过对返回的映射条目的 setValue 操作 iterator) 迭代的结果是不确定的。

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 2012-08-22
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 2012-08-08
    • 2023-03-30
    • 2011-10-05
    • 1970-01-01
    • 2010-10-12
    相关资源
    最近更新 更多