【问题标题】:I am getting java.util.ConcurrentModificationException thrown while using HashMap我在使用 HashMap 时抛出 java.util.ConcurrentModificationException
【发布时间】:2012-07-28 05:15:19
【问题描述】:

与HashMap中的元素相比,如何删除下面代码中的键值对?

Map<BigDecimal, TransactionLogDTO> transactionLogMap = new HashMap<BigDecimal, TransactionLogDTO>();
for (BigDecimal regionID : regionIdList) {// Generation new logDTO
                                            // objects for each in scope
                                            // region
    transactionLogMap.put(regionID, new TransactionLogDTO());
}
Set<BigDecimal> inScopeActiveRegionIdSet = new HashSet<BigDecimal>();

for (PersonDTO personDTO4 : activePersons) {

    inScopeActiveRegionIdSet.add(personDTO4.getRegion());

}

for (BigDecimal bigDecimal : transactionLogMap.keySet()) {
    if (!inScopeActiveRegionIdSet.contains(bigDecimal)) {
        transactionLogMap.remove(bigDecimal);
    }
}

【问题讨论】:

    标签: java collections hashmap hashset


    【解决方案1】:

    或者,如果inScopeActiveRegionIdSet 的大小更小,那么迭代它可能会更短更快:

    for (BigDecimal bigDecimal : inScopeActiveRegionIdSet) {
        transactionLogMap.remove(bigDecimal);
    }
    

    【讨论】:

      【解决方案2】:

      问题出在这几行

      for (BigDecimal bigDecimal : transactionLogMap.keySet()) {
          if(!inScopeActiveRegionIdSet.contains(bigDecimal)) {
              transactionLogMap.remove(bigDecimal);
          }
      }
      

      当您调用transactionLogMap.remove 时,您正在遍历transactionLogMap,同时还直接修改底层Collection,这是不允许的,因为增强的for 循环无法看到这些更改。

      正确的解决方法是使用Iterator:

      Iterator<BigDecimal> it = transactionLogMap.keySet().iterator();//changed for syntax correctness
      while (it.hasNext()) {
          BigDecimal bigDecimal = it.next();
          if(!inScopeActiveRegionIdSet.contains(bigDecimal)) {
              it.remove();
          }
      }
      

      【讨论】:

        【解决方案3】:

        根据 javadoc

        ConcurrentModificationException 可能会被检测到对象的并发修改的方法抛出,而这种修改是不允许的

         transactionLogMap.remove(bigDecimal);
        

        使用Iterator 代替for loop 并在迭代器上调用remove。

        例子:

        Iterator iter = transactionLogMap.keySet().iterator();
        while(iter.hasNext())
        {
        iter.remove();
        }
        

        您可以考虑使用ConcurrentHashMap

        注意:输入代码,作为参考。可能存在语法错误。

        【讨论】:

          【解决方案4】:

          在迭代集合时,您不能从集合中删除项目。这会导致您遇到异常。

          当你打电话时:

          for(TypeX x: collectionOfX){ ... }
          

          幕后发生的事情是,您正在为 collectionOfX 创建一个迭代器,并进行迭代,直到您明确地从循环中中断或迭代器的 hasNext() 为 false。

          如果您需要在迭代期间从集合中删除项目,则需要将 foreach 构造替换为对迭代器的显式调用。比如:

          Iterator<BigDecimal> iter = transactionLogMap.keySet().iterator();
          while(iter.hasNext()) {
             BigDecimal bDecimal = iter.next();
             ...
             iter.remove(); //this will remove the current item from the collection, without raising an exception.
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-01-13
            • 1970-01-01
            • 2018-10-02
            • 1970-01-01
            • 2014-09-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多