Challenge Engineer Life !

エンジニア人生を楽しみたい!仕事や趣味で学んだ技術的なことを書いていくブログです。

Java Puzzlerとは言えないけどJavaの要素削除で理解できなくて頭を抱えたコード

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です。

まあ、JavaDocArrayListの部分を読むと、駄目よ、と書いてるので、まあそもそもやるなという話ですね(^^;
http://docs.oracle.com/javase/jp/7/api/java/util/ArrayList.html

ちなみにC#2.0(手元にVisualStudio2005しかないので…)で試したら後ろから2番目だろうが、ちゃんと駄目でした(^^;当たり前か

にほんブログ村 IT技術ブログへ
にほんブログ村 にほんブログ村 IT技術ブログ Javaへ
にほんブログ村