Challenge Engineer Life !

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

Javaでリストをループでまわして要素削除するのにハマったこと

以下色々なサイトで既出なのですが、自戒を込めて書いておこう(-_-;

仕事で書いてたプログラムですが、よくある「リストをループでまわして要素を削除する」処理で少しハマってました。実行時にjava.lang.UnsupportedOperationExceptionで落ちるっていう。

まず「リストをループでまわして要素を削除する」処理についてJavaで標準的なのって何だろと調べた所、StackOverflowにありました。

Calling remove in foreach loop in Java

結構評価あるのでiterator使うのが良いみたい。

以下はブログ用に簡単なコードにしてみました。

まずは普通に成功するパターン。

package arrayloopremove;

import java.util.ArrayList;
import java.util.Iterator;
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);

        Iterator<String> i = meiboList.iterator();
        while(i.hasNext()){
            String name = i.next();
            //接頭辞が「堀北」以外は除外
            if(!name.startsWith("堀北")){
                i.remove();
            }
        }
        
        System.out.println("remove後 -> " + meiboList);
    }
}

実行結果
remove前 -> [堀北真希, 能年玲奈, 宮崎あおい]
remove後 -> [堀北真希]

これを以下のように書いてました(^^;
最初のリスト定義が違うだけで、それ以降は上記と同じコードです。

package arrayloopremove;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class ArrayLoopRemove {

    public static void main(String[] args) {
        //名簿リストを配列から生成しただけ
        List<String> meiboList = Arrays.asList("堀北真希", "能年玲奈", "宮崎あおい");

        System.out.println("remove前 -> " + meiboList);

        Iterator<String> i = meiboList.iterator();
        while(i.hasNext()){
            String name = i.next();
            //接頭辞が「堀北」以外は除外
            if(!name.startsWith("堀北")){
                i.remove();
            }
        }
        
        System.out.println("remove後 -> " + meiboList);
    }
}

実行結果
remove前 -> [堀北真希, 能年玲奈, 宮崎あおい]
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
at arrayloopremove.ArrayLoopRemove.main(ArrayLoopRemove.java:39)
Java Result: 1

えー、なんでダメなの?なぞだー、とハマってた(^^;
原因は最初にあげた参考元の以下ブログに書いてあります。
悪あがきプログラマー - String配列から指定要素を削除する。

で、以下ならいける。地味にハマったなぁ。

package arrayloopremove;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class ArrayLoopRemove {

    public static void main(String[] args) {
        List<String> meiboList = new ArrayList<>();
        meiboList.addAll(Arrays.asList("堀北真希", "能年玲奈", "宮崎あおい"));
        
        System.out.println("remove前 -> " + meiboList);
        
        Iterator<String> i = meiboList.iterator();
        while(i.hasNext()){
            String name = i.next();
            //接頭辞が「堀北」以外は除外
            if(!name.startsWith("堀北")){
                i.remove();
            }
        }
        
        System.out.println("remove後 -> " + meiboList);
    }
}
にほんブログ村 IT技術ブログへ
にほんブログ村 にほんブログ村 IT技術ブログ Javaへ
にほんブログ村