質問: new ArrayList<>(); list.add("A"); list.add("B"); list.add("C"); list.add("D"); list.add("E"); for (String str : list){ if("C".equals(str)){ list.remove(str); } } for (String str : list){ System.out.println(str); } ``` *クラスの宣言とmainメソッドは省略しました。 --- このソース1の実行した結果として A が出力。 --- ソース2は実行時に例外がスローされるとあります。 ConcurrentModificationException←これ その理由として、ループで読みだしている最中にremoveメソッドを呼び出しているからとあります。 しかし、ソース1でもremoveメソッドを呼び出しているのにソース1では例外がスローされません。***これはなぜでしょうか?*** 私なりの考察。 ------- ソース1では拡張for文2回目のループでremoveメソッドが処理され3買い目のループは要素がなくなり2回目で終わり、残りの要素に影響されない。 ソース2では拡張for文3回目のループでremoveメソッドが処理され4回目ループの際の"E"がまだ残っているため要素数の順番に影響があるから? --- よろしくお願いします。
回答: 大まかに言うと考察はあってます。 要素数の順番ではなく、ループ中に要素数が変わることでエラーになります。 またソース1を実行した際も、 直感的にはAとCが出力されることが期待値になると思うのでエラーですよね。 ということで、普通ループ中に要素追加削除をするのはNGになっています。 stacktraceとclassファイル見ると多少詳しくと思うんですが、 ``` java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) at java.util.ArrayList$Itr.next(ArrayList.java:851) ``` ``` Iterator arg2 = e.iterator(); while(arg2.hasNext()) { String str = (String)arg2.next(); if("B".equals(str)) { e.remove(str); } else { System.out.println(str); } } ``` `ArrayList$Itr.checkForComodification`で要素数のチェック・エラー判定を行っているので、 ソース1の場合はremoveした後に次のhasNextでループを抜けるため、 nextが呼ばれずエラーになりません。