在迭代期间替换/更改HashMap项

时间:2012-01-08 10:08:58

标签: java hashmap

当我尝试从HashMap中删除项目时,我得到了Concurrent Modification Exception。我知道在迭代过程中通过HashMap删除项目会触发此异常,但我需要用新的项目替换旧项目。我怎样才能做到这一点 ?也许创建一个countNumberOfEachCharacter HashMap的副本,并循环通过原始的HashMap从复制HashMap中删除项目?

countNumberOfEachCharacter = new HashMap<Character,Character>();
if (countNumberOfEachCharacter.containsKey(word.charAt(i))) {
    System.out.println("This character already exists");                     
    for (Iterator it = countNumberOfEachCharacter.entrySet().iterator(); it.hasNext();) {

      Map.Entry entry = (Map.Entry) it.next();

      Object key = entry.getKey();
      Object value = entry.getValue();

      if (key.equals(word.charAt(i))) { 

        int toIncrease = Integer.parseInt(value.toString());
        toIncrease++;

        System.out.println("key  "+key);                                                     
        System.out.println("increased  "+toIncrease);                                                       
        countNumberOfEachCharacter.remove(word.charAt(i));

        char c = Character.forDigit(toIncrease, 10);                                                     
        countNumberOfEachCharacter.put(word.charAt(i),c);                                                                                                                                                                               
    }                                                                                                                                                                                                           
  }                                                                           
}
else {    

   System.out.println("First time found this character");

   char c = Character.forDigit(1, 10);                                
   countNumberOfEachCharacter.put(word.charAt(i),c);                            
   System.out.println("Stored "+word.charAt(i)+" with count "+c);                                                               
}

3 个答案:

答案 0 :(得分:2)

在迭代Collection时,您只能使用Iterator#remove方法删除元素。这也在HashMap

的类javadoc中记录
  

所有这类&#34;集合视图返回的迭代器   方法&#34;快速失败:如果地图在任何地方进行了结构修改   创建迭代器之后的时间,除了通过之外的任何方式   迭代器自己的remove方法,迭代器会抛出一个   ConcurrentModificationException的。因此,面对并发   修改,迭代器快速而干净地失败,而不是   在不确定的时间冒着任意的,非确定性的行为   将来

此外,对于您要执行的操作(=更新值),您不必将其删除。只需使用该密钥和更新值调用put,这将更新值,如HashMap#put方法的javadoc中所述

  

将指定的值与此映射中的指定键相关联。如果   地图以前包含键的映射,旧值是   替换。

答案 1 :(得分:1)

  

...但我需要用新的项目替换旧项目

我从“替换”(以及你引用的代码)中取出保持不变,它只是不同的值。如果是这样,我不相信在Map.Entry个对象上调用setValue会导致ConcurrentModificationException,所以你可以这样做。

更新:刚试过它,确实有效:

import java.util.*;

public class ReplaceMapEntryValue {

    public static final void main(String[] args) {
        Map m;
        Iterator<Map.Entry> it;
        Map.Entry entry;

        // Create
        m = new HashMap();
        m.put("a", "alpha");
        m.put("b", "beta");

        // Update
        it = m.entrySet().iterator();
        while (it.hasNext()) {
            entry = it.next();
            if (entry.getKey() == "b") {
                entry.setValue("bravo");
            }
        }

        // Show
        it = m.entrySet().iterator();
        while (it.hasNext()) {
            entry = it.next();
            System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());
        }

        // Done
        System.exit(0);
    }
}

答案 2 :(得分:0)

地图的重点是你可以按键查找,你不必检查每个条目。

Map<Character, AtomicInteger> countNumberOfEachCharacter = new TreeMap<Character, AtomicInteger>();

String word = "the quick brown fox jumps over the lazy dog";
for (int i = 0; i < word.length(); i++) {
    AtomicInteger count = countNumberOfEachCharacter.get(word.charAt(i));
    if (count == null)
        countNumberOfEachCharacter.put(word.charAt(i), new AtomicInteger(1));
    else
        count.incrementAndGet();
}
System.out.println("Character count: " + countNumberOfEachCharacter);

打印

Character count: { =8, a=1, b=1, c=1, d=1, e=3, f=1, g=1, h=2, i=1, j=1, k=1, l=1, m=1, n=1, o=4, p=1, q=1, r=2, s=1, t=2, u=2, v=1, w=1, x=1, y=1, z=1}

但是,由于您有一些固定数量的小字符,因此您甚至不需要使用地图

int[] countNumberOfEachCharacter = new int[Character.MAX_VALUE + 1];

String word = "the quick brown fox jumps over the lazy dog";
for (int i = 0; i < word.length(); i++)
    countNumberOfEachCharacter[word.charAt(i)]++;

System.out.print("Character count: ");
for (int i = 0; i < countNumberOfEachCharacter.length; i++)
    if (countNumberOfEachCharacter[i] > 0)
        System.out.print(" " + (char) i + "=" + countNumberOfEachCharacter[i]);
System.out.println();

打印

Character count:   =8 a=1 b=1 c=1 d=1 e=3 f=1 g=1 h=2 i=1 j=1 k=1 l=1 m=1 n=1 o=4 p=1 q=1 r=2 s=1 t=2 u=2 v=1 w=1 x=1 y=1 z=1