web-dev-qa-db-ja.com

Arrays.asList(array)と新しいArrayList <Integer>(Arrays.asList(array))の違い

違いは何ですか

1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy
2.List<Integer> list2 = Arrays.asList(ia);

ここで、iaは整数の配列です。

list2では一部の操作が許可されていないことを知りました。なぜそうですか?どのようにメモリに保存されますか(参照/コピー)?

リストをシャッフルすると、list1は元の配列に影響を与えませんが、list2は影響します。しかし、まだlist2はやや混乱しています。

ArrayListがリストにアップキャストされる方法と、新しいArrayListを作成する方法との違い

list1 differs from (1)
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
95
Dineshkumar
  1. まず、これが何をするのか見てみましょう:

    Arrays.asList(ia)
    

    配列iaを受け取り、List<Integer>を実装するラッパーを作成します。これにより、元の配列がリストとして使用可能になります。何もコピーされず、すべて、単一のラッパーオブジェクトのみが作成されます。リストラッパーの操作は、元の配列に伝達されます。これは、リストラッパーをシャッフルすると元の配列もシャッフルされることを意味します。要素を上書きすると、元の配列で上書きされます。もちろん、追加など、一部のList操作はラッパーでは許可されませんリストから要素を削除した場合、要素の読み取りまたは上書きのみが可能です。

    リストラッパーはArrayListを拡張しないことに注意してください-これは異なる種類のオブジェクトです。 ArrayListsには独自の内部配列があり、要素を格納し、内部配列などのサイズを変更できます。ラッパーは独自の内部配列を持たず、指定された配列に操作を伝播するだけです。

  2. 一方、後で新しい配列を作成すると

    new ArrayList<Integer>(Arrays.asList(ia))
    

    次に、新しいArrayListを作成します。これは、元のコピーの完全な独立したコピーです。ここではArrays.asListを使用してラッパーを作成しますが、新しいArrayListの構築中にのみ使用され、後でガベージコレクションされます。この新しいArrayListの構造は、元の配列から完全に独立しています。同じ要素(元の配列とこの新しいArrayListの両方がメモリ内の同じ整数を参照します)を含みますが、参照を保持する新しい内部配列を作成します。したがって、要素をシャッフル、追加、削除するときなど、元の配列は変更されません。

190
Petr Pudlák

これは、Arrays.asList()の結果であるArrayListJava.util.ArrayList型ではないためです。 Arrays.asList()は、Java.util.Arrays$ArrayListを拡張せず、Java.util.ArrayListのみを拡張するタイプJava.util.AbstractListArrayListを作成します

23
Chris
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy

この場合、list1ArrayList型です。

List<Integer> list2 = Arrays.asList(ia);

ここでは、リストはListビューとして返されます。これは、そのインターフェイスにメソッドのみがアタッチされていることを意味します。したがって、いくつかのメソッドがlist2で許可されない理由。

ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));

ここでは、新しいArrayListを作成しています。コンストラクタで値を渡すだけです。これはキャストの例ではありません。キャストでは、次のようになります。

ArrayList list1 = (ArrayList)Arrays.asList(ia);
8
christopher

私はここでかなり遅れていますが、とにかく答えを探している人にはドキュメント参照の説明が良いと感じました。

  1. Java.util.Arrays
  • これは、特定の配列を操作するための静的メソッドの束を持つユーティリティクラスです
  • asList は、入力配列を受け取り、Listインターフェイスを実装するAbstractListを拡張する静的なネストされたクラスであるJava.util.Arrays.ArrayListのオブジェクトを返す静的メソッドの1つです。 。
  • したがって、Arrays.asList(inarray)は入力配列の周囲にリストラッパーを返しますが、このラッパーはJava.util.ArrayListではなく、同じ配列を参照するため、さらに追加されます。リストラップされた配列の要素は元の配列にも影響し、長さを変更することもできません。
  1. Java.util.ArrayList
  • ArrayListには多数のオーバーロードされたコンストラクタがあります

    public ArrayList()-//デフォルトの容量10で配列リストを返します

    public ArrayList(コレクションc)

    public ArrayList(int initialCapacity)

  • したがって、Arrays.asListから返されたオブジェクト、つまりList(AbstractList)を上記の2番目のコンストラクターに渡すと、新しい動的配列が作成されます(この配列サイズは、容量より多くの要素を追加すると増加し、新しい要素は元の配列に影響しません)元の配列の浅いコピー( shallow copy は、参照のみをコピーし、元の配列と同じオブジェクトの新しいセットを作成しないことを意味します)

3
String names[] = new String[]{"Avinash","Amol","John","Peter"};
Java.util.List<String> namesList = Arrays.asList(names);

または

String names[] = new String[]{"Avinash","Amol","John","Peter"};
Java.util.List<String> temp = Arrays.asList(names);         

上記のステートメントは、入力配列にラッパーを追加します。したがって、追加と削除などのメソッドは、リスト参照オブジェクト「namesList」には適用できません。

既存の配列/リストに要素を追加しようとすると、「スレッド「メイン」Java.lang.UnsupportedOperationExceptionの例外」が発生します。

上記の操作は読み取り専用または表示専用です。
リストオブジェクトで追加または削除操作を実行できません。しかし

String names[] = new String[]{"Avinash","Amol","John","Peter"};
Java.util.ArrayList<String> list1 = new ArrayList<>(Arrays.asList(names));

または

String names[] = new String[]{"Avinash","Amol","John","Peter"};
Java.util.List<String> listObject = Arrays.asList(names);
Java.util.ArrayList<String> list1 = new ArrayList<>(listObject);

上記のステートメントでは、ArrayListクラスの具体的なインスタンスを作成し、パラメーターとしてリストを渡しました。

この場合、メソッドは両方ともArrayListクラスからであるため、メソッドの追加と削除は適切に機能するため、ここではUnSupportedOperationExceptionを取得しません。
Arraylistオブジェクトで行われた変更(arraylistの要素の追加または削除メソッド)は、元のJava.util.Listオブジェクトに反映されません。

String names[] = new String[] {
    "Avinash",
    "Amol",
    "John",
    "Peter"
};

Java.util.List < String > listObject = Arrays.asList(names);
Java.util.ArrayList < String > list1 = new ArrayList < > (listObject);
for (String string: list1) {
    System.out.print("   " + string);
}
list1.add("Alex"); //Added without any exception
list1.remove("Avinash"); //Added without any exception will not make any changes in original list in this case temp object.


for (String string: list1) {
    System.out.print("   " + string);
}
String existingNames[] = new String[] {
    "Avinash",
    "Amol",
    "John",
    "Peter"
};
Java.util.List < String > namesList = Arrays.asList(names);
namesList.add("Bob"); // UnsupportedOperationException occur
namesList.remove("Avinash"); //UnsupportedOperationException
3
Avinash Pande

Java 8では、上記の 'ia'はint []ではなくInteger []でなければならないことに注意してください。 int配列のArrays.asList()は、単一の要素を持つリストを返します。 OPのコードスニペットを使用する場合、コンパイラは問題をキャッチしますが、一部のメソッド(Collections.shuffle()など)は、期待どおりに静かに失敗します。

2
Carl Burke

まず、Arraysクラスは、noを含むユーティリティクラスです。配列を操作するユーティリティメソッドの一覧(配列クラスのおかげで、配列オブジェクトに作用する独自のメソッドを作成する必要がありました)

asList()メソッド:

  1. asListメソッドはArrayクラスのユーティリティメソッドの1つであり、静的メソッドであるため、クラス名でこのメソッドを呼び出すことができます(Arrays.asList(T...a)など)
  2. ここにひねりがあります。このメソッドは新しいArrayListオブジェクトを作成せず、既存のArrayオブジェクトへのリスト参照を返すだけです(したがって、asListメソッドを使用した後、既存のArrayオブジェクトへの参照が作成されます)
  3. これが理由であり、Listオブジェクトを操作するすべてのメソッドは、List参照のようなArray参照を使用してこのArrayオブジェクトで動作しない場合があります。このArray参照(list.add(10)list.remove(10);など)を使用してListオブジェクトの要素を追加または削除できません。そうでない場合はUnsupportedOperationExceptionがスローされます
  4. リスト参照を使用して行っている変更は、既存の配列オブジェクトをリスト参照を使用して操作しているため、既存のArraysオブジェクトに反映されます。

最初の場合、新しいArraylistオブジェクトを作成します(2番目の場合、既存のArrayオブジェクトへの参照のみが作成され、新しいArrayListオブジェクトは作成されません)。したがって、2つの異なるオブジェクトがArrayオブジェクトと別のオブジェクトはArrayListオブジェクトであり、それらの間の接続はありません(そのため、1つのオブジェクトの変更は別のオブジェクトに反映/影響されません(つまり、2 ArrayArraylistは2つの異なるオブジェクト)

ケース1:

Integer [] ia = {1,2,3,4};
System.out.println("Array : "+Arrays.toString(ia));
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  // new ArrayList object is created , no connection between existing Array Object
list1.add(5);
list1.add(6);
list1.remove(0);
list1.remove(0);
System.out.println("list1 : "+list1);
System.out.println("Array : "+Arrays.toString(ia));

ケース2:

Integer [] ia = {1,2,3,4};
System.out.println("Array : "+Arrays.toString(ia));
List<Integer> list2 = Arrays.asList(ia); // creates only a (new ) List reference to existing Array object (and NOT a new ArrayList Object)
//  list2.add(5); //  it will throw Java.lang.UnsupportedOperationException - invalid operation (as Array size is fixed)
list2.set(0,10);  // making changes in existing Array object using List reference - valid 
list2.set(1,11); 
ia[2]=12;     // making changes in existing Array object using Array reference - valid
System.out.println("list2 : "+list2);
System.out.println("Array : "+Arrays.toString(ia));
2
qaautodev

Arrays.asList()

このメソッドは、Listの独自の実装を返します。配列からデータをコピーするのではなく、元の配列を使用するため、変更時に元の配列が変更されるため、引数として配列を受け取り、その上にメソッドと属性を作成しますArrays.asList()メソッドによって返されるリスト。

一方。
ArrayList(Arrays.asList());は、リストを引数として取り、リストから独立したArrayListを返すArrayListクラスのコンストラクターです。この場合のArrays.asList()は引数として渡されます。そのため、これらの結果が表示されます。

1

多くの人がすでに機械的な詳細に答えていますが、注目に値します。これはJavaによる設計の選択としては不十分です。

JavaのasListメソッドは「Returns a fixed-size list ...」として文書化されています。その結果を取得して(たとえば).addメソッドを呼び出すと、UnsupportedOperationExceptionがスローされます。これは直感に反する動作です!メソッドがListを返すと言う場合、標準的な期待は、インターフェイスListのメソッドをサポートするオブジェクトを返すことです。開発者は、数え切れないほどのutil.Listメソッドのwhichを覚える必要はないはずです。実際には、すべてのListメソッドをサポートしていないListsを作成します。

メソッドにasImmutableListという名前を付けていれば、意味があります。または、メソッドが実際のListを返す(およびバッキング配列をコピーする)だけの場合、意味があります。彼らは、ランタイムパフォーマンスandショートネームの両方を優先することを決定しました。ただし、最小サプライズの原則とGood-O.O。 UnsupportedOperationExceptionsを避ける練習。

(また、設計者は、大量のUnsupportedOperationExceptionsを避けるために、interface ImmutableListを作成したかもしれません。)

1
not-just-yeti
package com.copy;

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

public class CopyArray {

    public static void main(String[] args) {
        List<Integer> list1, list2 = null;
        Integer[] intarr = { 3, 4, 2, 1 };
        list1 = new ArrayList<Integer>(Arrays.asList(intarr));
        list1.add(30);
        list2 = Arrays.asList(intarr);
        // list2.add(40); Here, we can't modify the existing list,because it's a wrapper
        System.out.println("List1");
        Iterator<Integer> itr1 = list1.iterator();
        while (itr1.hasNext()) {
            System.out.println(itr1.next());
        }
        System.out.println("List2");
        Iterator<Integer> itr2 = list2.iterator();
        while (itr2.hasNext()) {
            System.out.println(itr2.next());
        }
    }
}
1
VicXj

違いの概要-

new operator Arrays.asList()メソッドを使用せずにリストを作成すると、Wrapperを返します。つまり、

1。追加/更新操作を実行できます。

2。元の配列で行われた変更はリストにも反映され、その逆も同様です。

0
Raj

Java 8以降の Arrays.asList() の動作について質問するいくつかのコメントに応えて:

    int[] arr1 = {1,2,3};
    /* 
       Arrays are objects in Java, internally int[] will be represented by 
       an Integer Array object which when printed on console shall output
       a pattern such as 
       [I@address for 1-dim int array,
       [[I@address for 2-dim int array, 
       [[F@address for 2-dim float array etc. 
   */
    System.out.println(Arrays.asList(arr1)); 

    /* 
       The line below results in Compile time error as Arrays.asList(int[] array)
       returns List<int[]>. The returned list contains only one element 
       and that is the int[] {1,2,3} 
    */
    // List<Integer> list1 = Arrays.asList(arr1);

    /* 
       Arrays.asList(arr1) is  Arrays$ArrayList object whose only element is int[] array
       so the line below prints [[I@...], where [I@... is the array object.
    */
    System.out.println(Arrays.asList(arr1)); 

    /* 
     This prints [I@..., the actual array object stored as single element 
     in the Arrays$ArrayList object. 
    */
    System.out.println(Arrays.asList(arr1).get(0));

    // prints the contents of array [1,2,3]
    System.out.println(Arrays.toString(Arrays.asList(arr1).get(0)));

    Integer[] arr2 = {1,2,3};
    /* 
     Arrays.asList(arr) is  Arrays$ArrayList object which is 
     a wrapper list object containing three elements 1,2,3.
     Technically, it is pointing to the original Integer[] array 
    */
    List<Integer> list2 = Arrays.asList(arr2);

    // prints the contents of list [1,2,3]
    System.out.println(list2);
0
NINCOMPOOP
1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy
2.List<Integer> list2 = Arrays.asList(ia);

2行目では、Arrays.asList(ia)List内で定義された内部クラスオブジェクトのArrays参照を返します。これはArrayListとも呼ばれますが、プライベートで、AbstractListのみを拡張します。つまり、Arrays.asList(ia)から返されたものは、new ArrayList<Integer>から取得したものとは異なるクラスオブジェクトです。

Arrays内の内部プライベートクラスはこれらのメソッドを提供しないため、2行目には一部の操作を使用できません。

このリンクを見て、プライベート内部クラスでできることを確認してください: http://grepcode.com/file/repository.grepcode.com/Java/root/jdk/openjdk/6-b14/ Java/util/Arrays.Java#Arrays.ArrayList

1行目は、2行目から取得したものから要素をコピーする新しいArrayListオブジェクトを作成します。したがって、Java.util.ArrayListがすべてのメソッドを提供するので、何でもできます。

0
zek_w