違いは何ですか
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));
まず、これが何をするのか見てみましょう:
Arrays.asList(ia)
配列ia
を受け取り、List<Integer>
を実装するラッパーを作成します。これにより、元の配列がリストとして使用可能になります。何もコピーされず、すべて、単一のラッパーオブジェクトのみが作成されます。リストラッパーの操作は、元の配列に伝達されます。これは、リストラッパーをシャッフルすると元の配列もシャッフルされることを意味します。要素を上書きすると、元の配列で上書きされます。もちろん、追加など、一部のList
操作はラッパーでは許可されませんリストから要素を削除した場合、要素の読み取りまたは上書きのみが可能です。
リストラッパーはArrayList
を拡張しないことに注意してください-これは異なる種類のオブジェクトです。 ArrayList
sには独自の内部配列があり、要素を格納し、内部配列などのサイズを変更できます。ラッパーは独自の内部配列を持たず、指定された配列に操作を伝播するだけです。
一方、後で新しい配列を作成すると
new ArrayList<Integer>(Arrays.asList(ia))
次に、新しいArrayList
を作成します。これは、元のコピーの完全な独立したコピーです。ここではArrays.asList
を使用してラッパーを作成しますが、新しいArrayList
の構築中にのみ使用され、後でガベージコレクションされます。この新しいArrayList
の構造は、元の配列から完全に独立しています。同じ要素(元の配列とこの新しいArrayList
の両方がメモリ内の同じ整数を参照します)を含みますが、参照を保持する新しい内部配列を作成します。したがって、要素をシャッフル、追加、削除するときなど、元の配列は変更されません。
これは、Arrays.asList()
の結果であるArrayList
がJava.util.ArrayList
型ではないためです。 Arrays.asList()
は、Java.util.Arrays$ArrayList
を拡張せず、Java.util.ArrayList
のみを拡張するタイプJava.util.AbstractList
のArrayList
を作成します
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); //copy
この場合、list1
はArrayList
型です。
List<Integer> list2 = Arrays.asList(ia);
ここでは、リストはList
ビューとして返されます。これは、そのインターフェイスにメソッドのみがアタッチされていることを意味します。したがって、いくつかのメソッドがlist2
で許可されない理由。
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
ここでは、新しいArrayList
を作成しています。コンストラクタで値を渡すだけです。これはキャストの例ではありません。キャストでは、次のようになります。
ArrayList list1 = (ArrayList)Arrays.asList(ia);
私はここでかなり遅れていますが、とにかく答えを探している人にはドキュメント参照の説明が良いと感じました。
ArrayListには多数のオーバーロードされたコンストラクタがあります
public ArrayList()-//デフォルトの容量10で配列リストを返します
public ArrayList(コレクションc)
public ArrayList(int initialCapacity)
したがって、Arrays.asListから返されたオブジェクト、つまりList(AbstractList)を上記の2番目のコンストラクターに渡すと、新しい動的配列が作成されます(この配列サイズは、容量より多くの要素を追加すると増加し、新しい要素は元の配列に影響しません)元の配列の浅いコピー( shallow copy は、参照のみをコピーし、元の配列と同じオブジェクトの新しいセットを作成しないことを意味します)
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
Java 8では、上記の 'ia'はint []ではなくInteger []でなければならないことに注意してください。 int配列のArrays.asList()は、単一の要素を持つリストを返します。 OPのコードスニペットを使用する場合、コンパイラは問題をキャッチしますが、一部のメソッド(Collections.shuffle()など)は、期待どおりに静かに失敗します。
まず、Arraysクラスは、noを含むユーティリティクラスです。配列を操作するユーティリティメソッドの一覧(配列クラスのおかげで、配列オブジェクトに作用する独自のメソッドを作成する必要がありました)
asList
メソッドはArray
クラスのユーティリティメソッドの1つであり、静的メソッドであるため、クラス名でこのメソッドを呼び出すことができます(Arrays.asList(T...a)
など)ArrayList
オブジェクトを作成せず、既存のArray
オブジェクトへのリスト参照を返すだけです(したがって、asList
メソッドを使用した後、既存のArray
オブジェクトへの参照が作成されます)List
オブジェクトを操作するすべてのメソッドは、List
参照のようなArray
参照を使用してこのArrayオブジェクトで動作しない場合があります。このArray
参照(list.add(10)
やlist.remove(10);
など)を使用してList
オブジェクトの要素を追加または削除できません。そうでない場合はUnsupportedOperationExceptionがスローされますArray
sオブジェクトに反映されます。最初の場合、新しいArraylist
オブジェクトを作成します(2番目の場合、既存のArrayオブジェクトへの参照のみが作成され、新しいArrayList
オブジェクトは作成されません)。したがって、2つの異なるオブジェクトがArray
オブジェクトと別のオブジェクトはArrayList
オブジェクトであり、それらの間の接続はありません(そのため、1つのオブジェクトの変更は別のオブジェクトに反映/影響されません(つまり、2 Array
とArraylist
は2つの異なるオブジェクト)
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));
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));
Arrays.asList()
このメソッドは、Listの独自の実装を返します。配列からデータをコピーするのではなく、元の配列を使用するため、変更時に元の配列が変更されるため、引数として配列を受け取り、その上にメソッドと属性を作成しますArrays.asList()
メソッドによって返されるリスト。
一方。ArrayList(Arrays.asList());
は、リストを引数として取り、リストから独立したArrayList
を返すArrayList
クラスのコンストラクターです。この場合のArrays.asList()
は引数として渡されます。そのため、これらの結果が表示されます。
多くの人がすでに機械的な詳細に答えていますが、注目に値します。これはJavaによる設計の選択としては不十分です。
JavaのasList
メソッドは「Returns a fixed-size list ...」として文書化されています。その結果を取得して(たとえば).add
メソッドを呼び出すと、UnsupportedOperationException
がスローされます。これは直感に反する動作です!メソッドがList
を返すと言う場合、標準的な期待は、インターフェイスList
のメソッドをサポートするオブジェクトを返すことです。開発者は、数え切れないほどのutil.List
メソッドのwhichを覚える必要はないはずです。実際には、すべてのList
メソッドをサポートしていないList
sを作成します。
メソッドにasImmutableList
という名前を付けていれば、意味があります。または、メソッドが実際のList
を返す(およびバッキング配列をコピーする)だけの場合、意味があります。彼らは、ランタイムパフォーマンスandショートネームの両方を優先することを決定しました。ただし、最小サプライズの原則とGood-O.O。 UnsupportedOperationException
sを避ける練習。
(また、設計者は、大量のUnsupportedOperationException
sを避けるために、interface ImmutableList
を作成したかもしれません。)
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());
}
}
}
違いの概要-
new operator Arrays.asList()メソッドを使用せずにリストを作成すると、Wrapperを返します。つまり、
1。追加/更新操作を実行できます。
2。元の配列で行われた変更はリストにも反映され、その逆も同様です。
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);
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
がすべてのメソッドを提供するので、何でもできます。