2011年9月12日月曜日

ConcurrentModificationExceptionに対処してみる。

Mapのデータとかをあつかうときに、全体を検索してみつけたデータに特定の処理をかける…
そんな処理をするときにでてしまうのが、ConcurrentModificationException

問題が発生する原因は、ループをかけているときにマップの要素数が変更してしまうことにあります。

なので、こういうやり方はNG
Map<String, Object> targetMap;
ダメな例その1
for(String key : targetMap.keySet()) {
    targetMap.remove(key);
}
ダメな例その2
Iterator<String> iter = targetMap.keySet().iterator();
while(iter.hasNext()) {
    String key = iter.next();
    targetMap.remove(key);
}
ダメな例その3
for(Entry<String, Object> entry : targetMap.entrySet()) {
    targetMap.remove(entry.getKey());
}
というわけでどんなやり方してもダメです。

ただし例外があります。
1つは、キーセットを元のMapから切り離してしまう方法
for(String key : new HashSet<String>(targetMap.keySet())) {
    targetMap.remove(key);
}
これなら問題なく動作します。

もう1つの例外は要素数を変更したあとに、再ループしない場合です。

for(String key : targetMap.keySet()) {
    targetMap.remove(key);
    break;
}
これなら問題なく動作します。

特に後者はテストで動かしたときに要素数が1つだったりすると問題なく動作してしまうので、注意が必要ですね。

0 件のコメント:

コメントを投稿