[This blog post, thanks to the help of the Administrator Gg of cnblogs, allows us to see the day again. Thank you!]
A cute little bug when using set/Map: Java. util. concurrentmodificationexception
[Error scenario 1]: Set container, edge traversal, edge Add/Remove Element
Set<String> set = new HashSet<String>();
for (int i = 0; i < 10000; i++) {
set.add(Integer.toString(i));
}
For (string STR: Set) {// or use iterator for loop. For jdk5.0 or later, the underlying traversal is also implemented by iterator.
Set. Add ("XXX"); // Error
// Set. Remove (STR); // Error
}
[Error scenario 2]: Map container, edge traversal, and edge removal element
Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < 100; i++) {
map.put(Integer.toString(i), Integer.toString(i));
}
For (string STR: map. keyset () {// or use iterator to loop
Map. Remove (STR); // Error
}
[Error scenario 3] list container, edge traversal, edge Add/Remove Element
List<String> list = new ArrayList<String>();
for (int i = 0; i < 100; i++) {
list.add(Integer.toString(i));
}
for (Iterator<String> it = list.iterator(); it.hasNext();) {
String val = it.next();
if (val.equals("5")) {
List. Add (VAL); // Error
// List. Remove (VAL); // Error
}
}
[Error cause]
- For the remove operation, list. when removing (O), only modcount ++ is used, while the expectedcount value is not changed. When the iterator obtains the next element, it finds that the value of this binary value is not equal, and the concurrentmodificationexception is thrown.
- For the add operation
- See here for details: http://hi.baidu.com/sdausea/blog/item/57b2fa3dcb101908bba1672e.html
[Solution]
- Remove: use the original ecology remove () provided by iterator ()
Add: an error occurs when it is the same as remove. iterator does not provide the native add () method. Yes, you need to save the storage space with a new container, and then add it to the original container after the traversal is completed.
Set/list: for these two Common Containers, you can simply remove () and add () using the method described above.
Map: Use concurrenthashmap directly. Why can't other containers be used directly in a concurrent version ..? You can do it yourself.
[Correct Use Cases]
for (Iterator<String> it = list.iterator(); it.hasNext();) {
String val = it.next();
if (val.equals("5")) {
it.remove();
}
}
List<String> newList = new ArrayList<String>();
for (Iterator<String> it = list.iterator(); it.hasNext();) {
String val = it.next();
if (val.equals("5")) {
newList.add(val);
}
}
list.addAll(newList);