Reputation:
I get Concurrent Modification Exception when i try to remove an item from HashMap. I know that removing items during iteration through HashMap will trigger this exception , but i need to replace older item with new one. How can i do this ? Maybe to create a copy of countNumberOfEachCharacter HashMap , and whe iterate through original HashMap to remove item from copy 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);
}
Upvotes: 2
Views: 10205
Reputation: 533500
The whole point of a map is that you can lookup by key, you don't have to examine every entry.
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);
prints
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}
However since you have a small, fixed number of possible characters you don't even need to use a Map
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();
prints
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
Upvotes: 0
Reputation: 1074276
...but i need to replace older item with new one
I take it from "replace" (and from the code you've quoted) that the key remains the same, it's just the value that differs. If so, I don't believe calling setValue
on Map.Entry
objects causes a ConcurrentModificationException
, so you could do that.
Update: Just tested it, and indeed, it works:
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);
}
}
Upvotes: 1
Reputation: 36611
While iterating over a Collection
, you can only remove elements by using the Iterator#remove
method. This is also documented in the class javadoc of HashMap
The iterators returned by all of this class's "collection view methods" are fail-fast: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future
Furthermore for what you are trying to do (=update a value) you do not have to remove it. Just call put
with that key and an updated value, which will update the value, as documented in the javadoc of the HashMap#put
method
Associates the specified value with the specified key in this map. If the map previously contained a mapping for the key, the old value is replaced.
Upvotes: 2