🗒️

Arrays.asList(int())とArrays.asList(Integer[])の違い

2022/03/28に公開

Arrays.asList()を使って配列をリストに変換するとき、配列がプリミティブ型(primitive type)の場合と参照型(reference type)で挙動が異なると学んだのでまとめておく。

先にざっくりまとめると、

  1. Arrays.asList()はオートボクシングしない
  2. Arrays.asList()が返すリストは、長さが固定されているリスト

Arrays.asList(boolean[])での失敗

この事象に出くわしたのは、boolean[]に特定の数が含まれているかどうかを調べたいので、Listに変換してcontains()を使って調べたい!と思った時だった。

例えば、以下のように、配列内にfalseを含むかどうかでisAllTrueXの値を変えたい時、コードを実装した時に、予想外の動きをした。

isAllTrue_failed
boolean[] arr1 = new boolean[]{true,true,false,true,true};
boolean[] arr2 = new boolean[]{true,true,true,true,true};
boolean isAllTrue1 = false, isAllTrue2 = false;

if(!Arrays.asList(arr1).contains(false))
    isAllTrue1 = true;
if(!Arrays.asList(arr2).contains(false))
    isAllTrue2 = true;

System.out.println(isAllTrue1); // true
System.out.println(isAllTrue2); // true

arr1は明らかにfalseを含んでいるのでisAllTrue1falseであるべきなのに、出力結果はtrueになってしまう。

1.asList()はautoboxingしてくれない

調べてみると、int[]boolean[]のようなプリミティブ型の配列をasList()List<Integer>List<Boolean>に変換しようとしても、帰ってくるのはList<int a[]``List<boolean b[]>となる。要は、asList()はautoboxingしてくれないため、引き数として与えられた配列を、そのまま格納しているだけ、という結果になる。

Arrays.asList(arr) 帰ってくる値 具体例
理想 List<Boolean> [true, true, false, true, true]
現実 List<boolean arr[]> [[true, true, false, true, true]]

https://www.geeksforgeeks.org/arrays-aslist-method-in-java-with-examples/

当然のことながら、これではCollection関連の機能が思ったようには機能しない。もちろん、contains()も機能しないので、isAllTrue_failedの例では思ったような動きをしてくれないのだ。

GeeksforGeeksによると、Integer, Booleanのようにラッパークラス(Wrapper class)の配列であればasList()で問題なく機能する。これも、Arrays.asList()はオートボクシングしないという特性から考えたら特に不思議なことはないと思う。

2.asList()は長さが変えられない配列を返す

これも一緒におさえておくべき特徴だろう。

公式ドキュメントによれば、Arrays.asList()で変換された結果は、元の配列にも反映されるようになっている。[1]

Integer[] integerArray = new Integer[]{1,2,3,4,5};
List<Integer> integerList = Arrays.asList(integerArray); // [1, 2, 3, 4, 5]
integerList.set(4,10);
System.out.println(integerList.get(4).equals(integerArray[4])); // true

この例の場合、integerArrayintegerListは互いに参照しあっているような状態だ。そのため、 integerListは配列の「長さは固定」という特徴も引き継いでいることになる。そのため、List型になったとはいえ、integerListの挙動もある程度の制限がある。例えば、新しい要素を追加しようとすると、もれなくexceptionが返ってくる。

integerList.add(11); // UnsupportedOperationException

ちなみにArrays.asList()と逆の動きをするのは、Collection.toArray()

脚注
  1. こういう状態を表す言葉を昔学んだ気がするのに、全く出てこない。。。何かtermがあった気がする(というただのボヤきでした) ↩︎

Discussion

ログインするとコメントできます