2012-01-08 3 views
2

Я получаю исключение Concurrent Modification Exception, когда пытаюсь удалить элемент из HashMap. Я знаю, что удаление элементов во время итерации через HashMap вызывает это исключение, но мне нужно заменить старый элемент на новый. Как я могу это сделать ? Может быть, создать копию countNumberOfEachCharacter HashMap и выполнить итерацию через оригинальный 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

Используйте 'ConcurrentHashMap' –

+0

@ Eng.Fouad это не устранит проблему, потому что нет параллельного доступа. Он просто перебирает его и удаляет элементы. –

ответ

1

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

я беру его с «заменить» (и из кода вы процитированный), что ключевых остается то же самое, это просто значение, которое отличается. Если это так, я не считаю, что вызов 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); 
    } 
} 
2

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

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

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

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

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 
Смежные вопросы