web-dev-qa-db-ja.com

List.ofとArrays.asListの違いは何ですか?

Java 9では、リスト用の新しいファクトリメソッド List.of が導入されました。

List<String> strings = List.of("first", "second");

以前のオプションと新しいオプションの違いは何ですか?つまり、これの違いは何ですか:

Arrays.asList(1, 2, 3);

この:

List.of(1, 2, 3);
87
user5908494

Arrays.asListは可変リストを返しますが、List.ofが返すリストは immutable です。

List<Integer> list = Arrays.asList(1, 2, null);
list.set(1, 10); // OK

List<Integer> list = List.of(1, 2, 3);
list.set(1, 10); // Fails with UnsupportedOperationException

Arrays.asListはnull要素を許可しますが、List.ofは許可しません:

List<Integer> list = Arrays.asList(1, 2, null); // OK
List<Integer> list = List.of(1, 2, null); // Fails with NullPointerException

containsは、nullとは異なる動作をします。

List<Integer> list = Arrays.asList(1, 2, 3);
list.contains(null); // Returns false

List<Integer> list = List.of(1, 2, 3);
list.contains(null); // Fails with NullPointerException

Arrays.asListは渡された配列のビューを返すため、配列への変更はリストにも反映されます。 List.ofの場合、これは正しくありません。

Integer[] array = {1,2,3};
List<Integer> list = Arrays.asList(array);
array[1] = 10;
System.out.println(list); // Prints [1, 10, 3]

Integer[] array = {1,2,3};
List<Integer> list = List.of(array);
array[1] = 10;
System.out.println(list); // Prints [1, 2, 3]
129
ZhekaKozlov

Arrays.asListList.of の違い

Stuart Marks(または以前のバージョン)の JavaDocs およびこの talk を参照してください。

コード例には次を使用します。

List<Integer> listOf = List.of(...);
List<Integer> asList = Arrays.asList(...);
List<Integer> unmodif = Collections.unmodifiableList(asList);

構造的な不変性(または:変更不可能)

List.ofを構造的に変更しようとすると、UnsupportedOperationExceptionになります。これには、addsetremoveなどの操作が含まれます。ただし、リスト内のオブジェクトの内容は変更できます(オブジェクトが不変でない場合)。そのため、リストは「完全に不変」ではありません。

これは、 Collections.unmodifiableList で作成された変更不可能なリストと同じ運命です。このリストのみが元のリストのviewなので、元のリストを変更すると変更できます。

Arrays.asListは完全に不変ではなく、setに制限はありません。

listOf.set(1, "a");  // UnsupportedOperationException
unmodif.set(1, "a"); // UnsupportedOperationException
asList.set(1, "a");  // modified unmodif! unmodif is not truly unmodifiable

同様に、バッキング配列を変更すると(保持している場合)、リストが変更されます。

構造的な不変性には、防御的なコーディング、同時実行性、セキュリティに関連する多くの副作用が伴いますが、これらはこの答えの範囲を超えています。

ヌルの敵意

List.ofおよびJava 1.5以降のコレクションでは、nullを要素として使用できません。 nullを要素またはルックアップとして渡そうとすると、NullPointerExceptionになります。

Arrays.asListは1.2(Collections Framework)のコレクションであるため、nullsを使用できます。

listOf.contains(null);  // NullPointerException
unmodif.contains(null); // allowed
asList.contains(null);  // allowed

シリアル化された形式

List.ofはJava 9で導入されており、このメソッドで作成されたリストは独自の(バイナリ)シリアル化された形式を持っているため、以前のJDKバージョンではデシリアライズできません(バイナリ互換性なし)。ただし、たとえばJSONでデシリアライズできます。

身元

Arrays.asListは内部的にnew ArrayListを呼び出し、参照の不等式を保証します。

List.ofは内部実装に依存します。返されるインスタンスは参照の等価性を持つことができますが、これは保証されないため、それに依存することはできません。

asList1 == asList2; // false
listOf1 == listOf2; // true or false

リストの作成方法やサポートする操作に関係なく、リストに同じ要素が同じ順序で含まれている場合、リストは等しい( List.equals を介して)と言う価値があります。

asList.equals(listOf); // true i.f.f. same elements in same order

実装(警告:バージョンによって詳細が変わる可能性があります)

List.ofのリスト内の要素の数が2以下の場合、要素は特殊な(内部)クラスのフィールドに格納されます。例は、2つの要素(部分ソース)を格納するリストです:

static final class List2<E> extends AbstractImmutableList<E> {
    private final E e0;
    private final E e1;

    List2(E e0, E e1) {
        this.e0 = Objects.requireNonNull(e0);
        this.e1 = Objects.requireNonNull(e1);
    }
}

それ以外の場合は、Arrays.asListと同様の方法で配列に格納されます。

時間とスペースの効率

フィールドベース(size <2)のList.of実装は、一部の操作でわずかに高速に実行されます。例として、size()は配列の長さをフェッチせずに定数を返すことができ、contains(E e)は反復オーバーヘッドを必要としません。

List.ofを使用して変更不可能なリストを作成することも高速です。上記のコンストラクターを2つの参照割り当て(および任意の量の要素に対するもの)と比較します

Collections.unmodifiableList(Arrays.asList(...));

2つのリストとその他のオーバーヘッドが作成されます。スペースの観点から、UnmodifiableListラッパーといくつかのペニーを保存します。最終的に、同等のHashSetの節約はより説得力があります。


結論の時間:変更しないリストが必要な場合はList.ofを使用し、変更可能なリストが必要な場合はArrays.asListを使用します(上記を参照)。

22
user1803551

List.ofArrays.asListの違いを要約しましょう

  1. List.ofは、データセットが少なく変更されていない場合に最適に使用でき、Arrays.asListは、大きく動的なデータセットの場合に最適に使用できます。

  2. List.ofは、フィールドベースの実装を持ち、固定オーバーヘッドと要素ごとの両方の観点でヒープスペースを消費しないため、オーバーヘッドスペースが非常に少なくなります。 Arrays.asListは、初期化中にヒープ内により多くのオブジェクトを作成するため、より多くのオーバーヘッドスペースを必要とします。

  3. List.ofによって返されるコレクションは不変であるためスレッドセーフであるのに対し、Arrays.asListによって返されるコレクションは変更可能でスレッドセーフではありません。 (不変のコレクションインスタンスは、通常、可変の対応するインスタンスよりもはるかに少ないメモリを消費します。)

  4. List.ofnull要素を許可しませんが、Arrays.asListnull要素を許可します。

14
Mohit Tyagi