2013-03-22 3 views
2

Я пишу эту программу на Java и получаю java.util.ConcurrentModificationException. Выдержка из кода приведена ниже, пожалуйста, дайте мне знать, требуется ли больше кода.Исключение одновременной модификации в HashMap

for (String eachChar : charsDict.keySet()) { 
    if (charsDict.get(eachChar) < 2) { 
     charsDict.remove(eachChar); 
    } 
} 

charsDict определяется как

Map<String, Integer> charsDict = new HashMap<String, Integer>(); 

Пожалуйста, помогите мне :)

ответ

5

Вы должны использовать remove метод итератора:

for (Iterator<String> it = charsDict.keySet().iterator(); it.hasNext();) { 
    String eachChar = it.next(); 
    if (charsDict.get(eachChar) < 2) { 
     it.remove(); 
    } 
} 

Также обратите внимание, что поскольку вы должны получить доступ к ключу, а значение, было бы более эффективно использовать entrySet вместо:

for (Iterator<Map.Entry<String, Integer>> it = charsDict.entrySet().iterator(); it.hasNext();) { 
    Map.Entry<String, Integer> e = it.next(); 
    String eachChar = e.getKey(); 
    int value = e.getValue(); 
    if (value < 2) { 
     it.remove(); 
    } 
} 

И, наконец, кажется, что ключ фактически не используется, поэтому цикл становится:

for (Iterator<Integer> it = charsDict.values().iterator(); it.hasNext();) { 
    if (it.next() < 2) { 
     it.remove(); 
    } 
} 

См. Также this related post.

+1

Принимает это как код более кратким. Спасибо :) Кроме того, я узнал, что итераторы находятся в процессе. Однако я должен добавить, что код Heuster также отлично работает. – pratnala

+0

@pratnala Да, другой ответ тоже работает, но с итератором вы избегаете создания ненужного списка и дважды запрашиваете карту (получите + удалить). – assylias

+0

Woah! Просто перебирайте значения и удаляйте значение. Но не связано ли значение с ключом? Итак, как все иначе? Кроме того, что код чище, чем есть. – pratnala

6

Вы не разрешается удалять элементы из карты при использовании его итератор.

Типичное решение для преодоления этого:

List<String> toBeDeleted = new ArrayList<String>(); 
for (String eachChar : charsDict.keySet()) { 
    if (charsDict.get(eachChar) < 2) { 
     toBeDeleted.add(eachChar); 
    } 
} 

for (String eachChar : toBeDeleted) { 
    charsDict.remove(eachChar); 
} 
+0

Это не очень эффективно. – assylias

+2

@assylias true, но обычно это не имеет значения. Тем не менее, мне нравится ваш ответ. –

-2

Использование ConcurrentHashMap может быть лучшим выбором, если sahred между потоками ... итератор не потокобезопасны и вы должны создать новый итератор InstEd использования того же между потоками.

+1

Вы полностью упустили точку. – EJP

Смежные вопросы