Заменить / изменить элементы HashMap во время итерации - PullRequest
2 голосов
/ 08 января 2012

Я получаю исключение одновременной модификации, когда пытаюсь удалить элемент из HashMap.Я знаю, что удаление элементов во время итерации через 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 ]

2 голосов
/ 08 января 2012

Итерируя по Collection, вы можете удалять элементы только с помощью метода Iterator#remove. Это также задокументировано в классе Javadoc HashMap

Итераторы, возвращаемые представлением коллекции этого класса методы "безотказны: если карта структурно модифицирована в любом время после создания итератора, любым способом, кроме как через собственный метод удаления итератора, итератор выдаст ConcurrentModificationException. Таким образом, перед лицом одновременного модификация, итератор дает сбой быстро и чисто, а не риск произвольного, недетерминированного поведения в неопределенное время в будущем

Кроме того, для того, что вы пытаетесь сделать (= обновить значение), вам не нужно его удалять. Просто вызовите put с этим ключом и обновленным значением, которое обновит значение, как описано в javadoc метода HashMap#put

Связывает указанное значение с указанным ключом на этой карте. Если карта ранее содержала отображение для ключа, старое значение заменен.

1 голос
/ 08 января 2012

... но мне нужно заменить старый элемент на новый

Я беру это от "заменить" (и из кода, который вы цитировали), что клавиша остается прежней, отличается только значение.Если это так, я не верю, что вызов setValue для Map.Entry объектов приводит к 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);
    }
}
0 голосов
/ 08 января 2012

Весь смысл карты в том, что вы можете искать по ключу, вам не нужно проверять каждую запись.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...