なみひらブログ

学んだことを日々記録する。~ since 2012/06/24 ~

Arrays.asListが返すListの仕様について

背景

Java8でCollectionインターフェースに追加されたremoveIf()を試そうと思ったら、別件でエラーが発生したのでメモっときます。

修飾子と型 メソッドと説明
default boolean removeIf(Predicate filter)
指定された述語を満たすこのコレクションの要素をすべて削除します。

内容

テスト書く。

@Test
public void test_removeIf(){
    // setup
    final List<String> words = Arrays.asList("a", "b", "b", "c");
    System.out.println("before : " + words);

    // action
    words.removeIf(w -> w.equals("b"));

    // check
    System.out.println("after : " + words);
}

実行した。

java.lang.UnsupportedOperationException
	at java.util.AbstractList.remove(AbstractList.java:161)
	at java.util.AbstractList$Itr.remove(AbstractList.java:374)
	at java.util.Collection.removeIf(Collection.java:415)
    (以下、略)

あれっ(;´Д`)と思って調べたら、Arrays.asListの仕様は以下の通りで「固定サイズのList」を返却するようでサイズ変更などは認められないとのこと。

修飾子と型 メソッドと説明
static List asList(T... a)
指定された配列に連動する固定サイズのリストを返します。

盲点でした(;´Д`)今まで意識せずに使っていました。要素の追加もできないし、削除も出来ない。

修正した。

@Test
public void test_removeIf(){
    // setup
    final List<String> words = new ArrayList<>(Arrays.asList("a", "b", "b", "c"));
    System.out.println("before : " + words);

    // action
    words.removeIf(w -> w.equals("b"));

    // check
    System.out.println("after : " + words);
}

結果:エラーなしで、Listの中身を削除できた。

before : [a, b, b, c]
after : [a, c]

参考

java - Why I get UnsupportedOperationException when trying to remove from the List? - Stack Overflow

java - remove() on List created by Arrays.asList() throws UnsupportedException - Stack Overflow