Javaを長らくやられてる方からするとピンとくるのかもしれないですが…。
先日「Javaでリストをループでまわして要素削除するのにハマったこと」を書きましたが、若手から「ループで要素ぶっこ抜いても動きますよ(ドヤ」と言われたコードが以下でした。
普通に拡張for文の中で要素削除してるコード(^^;
package arrayloopremove;
import java.util.ArrayList;
import java.util.List;
public class ArrayLoopRemove {
public static void main(String[] args) {
List<String> meiboList = new ArrayList<>();
meiboList.add("堀北真希");
meiboList.add("能年玲奈");
meiboList.add("宮崎あおい");
System.out.println("remove後 -> " + meiboList);
for(String name : meiboList){
if(name.startsWith("能年")){
meiboList.remove(name);
}
}
System.out.println("remove後 -> " + meiboList);
}
}
普通に「え、駄目じゃない?ConcurrentModificationException出ると思うよ」と言いつつ実行してみると…
remove後 -> [堀北真希, 能年玲奈, 宮崎あおい]
remove後 -> [堀北真希, 宮崎あおい]
動いた!ええっ…なぜ…。
………
……
…
わからんです(-_-;
ちなみにですが、ループ内のstartWithを"堀北"や"宮崎"にすると
remove後 -> [堀北真希, 能年玲奈, 宮崎あおい]
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
at java.util.ArrayList$Itr.next(ArrayList.java:791)
at arrayloopremove.ArrayLoopRemove.main(ArrayLoopRemove.java:32)
Java Result: 1
とConcurrentModificationExceptionになります。
「ほら、やっぱり出るじゃん!」
「でも、さっきの出ませんでしたよね?」
と、謎すぎる orz
中々わからなくて、ググってみたら以下の記事がドンピシャっぽい。
Listを直接変更してもIteratorがConcurrentModificationExceptionをスローしない件
Listの最後から2番目って…(^^;でも確かに要素をもう1つ追加して後ろから2番目を消すと消せる;
remove後 -> [堀北真希, 能年玲奈, 宮崎あおい, 橋本愛]
remove後 -> [堀北真希, 能年玲奈, 橋本愛]
まあ、そもそもこういう処理したら駄目というのは割と既知のことなので、普通はしないと思うのですが、こんな風にたまたま動いてしまうケースがあって怖いのぉ…と。
なおJDKは7です。
まあ、JavaDocでArrayListの部分を読むと、駄目よ、と書いてるので、まあそもそもやるなという話ですね(^^;
http://docs.oracle.com/javase/jp/7/api/java/util/ArrayList.html
ちなみにC#2.0(手元にVisualStudio2005しかないので…)で試したら後ろから2番目だろうが、ちゃんと駄目でした(^^;当たり前か