はじめに
ConcurrentModificationException が Java で発生したときの対処方法.
以下のようなコードを実行すると, 例外発生.
import java.util.Set;
import java.util.HashSet;
public class ConcurrentModification {
public static void main (String[] args) {
Set<Integer> set = new HashSet<Integer>();
for (int i = 0; i < 5; i++)
set.add (i);
for (Integer i: set) {
if (i == 3) {
set.remove (i);
}
}
}
}
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry (HashMap.java:922)
at java.util.HashMap$KeyIterator.next (HashMap.java:956)
at ConcurrentModification.main (ConcurrentModification.java:10)
原因は, iterater で for 文を回している時に, 要素を削除しようとしたから.
回避方法
その 1: イテレータを利用しない
イテレータなんてつかってかっこつけているのが悪い. Index で for 文をまわす
for (int i=0; i < set.size (); i++) {
if (i == 3) {
set.remove (i);
}
}
その 2 Concurrent ライブラリを利用する
ConcurrentHashMap を利用する. ただし, ConcurrentHashSet はない…以下のように対応
Set<Integer> set = Collections.newSetFromMap (new ConcurrentHashMap<Integer, Boolean>());
その 3 コレクションをコピーして回す
すこし冗長か?
Set<Integer> set = new HashSet<Integer>();
for (int i = 0; i < 5; i++)
set.add (i);
Set<Integer> set2 = new HashSet<Integer>();
set2.addAll (set);
for (Integer i: set2) {
if (i == 3) {
set.remove (i);
}
}
おわりに
やりかたはいろいろある. 1 がいいかな…