[java] Arrays.asList (array)와 new 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));
답변
-
먼저 이것이 무엇을하는지 봅시다 :
Arrays.asList(ia)
배열을 취하고
ia
를 구현하는 래퍼List<Integer>
를 만들어 원래 배열을 목록으로 사용할 수 있도록합니다. 아무것도 복사되지 않고 모두 하나의 래퍼 개체 만 만들어집니다. 목록 래퍼에 대한 작업은 원래 배열로 전파됩니다. 즉, 목록 래퍼를 섞으면 원래 배열도 섞이고 요소를 덮어 쓰면 원래 배열에서 덮어 쓰게됩니다. 물론 일부List
래퍼에서 추가 또는 추가와 같은 작업은 허용되지 않습니다. 목록에서 요소를 제거하면 요소를 읽거나 덮어 쓸 수만 있습니다.목록 래퍼는 확장되지 않으며
ArrayList
다른 종류의 개체입니다.ArrayList
s에는 요소를 저장하고 내부 배열의 크기를 조정할 수있는 자체 내부 배열이 있습니다. 래퍼에는 자체 내부 배열이 없으며 주어진 배열로 작업을 전파 할뿐입니다. -
반면에 다음과 같이 새 어레이를 생성하면
new ArrayList<Integer>(Arrays.asList(ia))
그런 다음
ArrayList
원본과 완전히 독립적 인 복사 본인 new를 만듭니다 . 여기서도 사용하여 래퍼를 만들지Arrays.asList
만 새 구성 중에 만 사용되며ArrayList
나중에 가비지 수집됩니다. 이 새로운 구조ArrayList
는 원래 배열과 완전히 독립적입니다. 동일한 요소 (원래 배열과이 새로운ArrayList
참조 모두 메모리에서 동일한 정수를 참조)를 포함하지만 참조를 보유하는 새로운 내부 배열을 만듭니다. 따라서 셔플, 요소 추가, 제거 등을 할 때 원래 배열은 변경되지 않습니다.
답변
ArrayList
결과 결과 Arrays.asList()
가 유형 이 아니기 때문 java.util.ArrayList
입니다. Arrays.asList()
생성 ArrayList
유형의 java.util.Arrays$ArrayList
확장하지 않는이 java.util.ArrayList
있지만 확장java.util.AbstractList
답변
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);
답변
나는 여기에 꽤 늦었지만 어쨌든 문서 참조가있는 설명이 답을 찾는 사람에게 더 좋을 것이라고 느꼈습니다.
- 이것은 주어진 배열에서 작동하는 여러 정적 메소드가있는 유틸리티 클래스입니다.
- asList 는 입력 배열을 취하고 List 인터페이스를 구현하는 AbstractList를 확장하는 정적 중첩 클래스 인 java.util.Arrays.ArrayList 의 객체를 반환하는 정적 메서드 중 하나 입니다.
- 따라서 Arrays.asList (inarray)는 입력 배열 주위에 List 래퍼를 반환하지만이 래퍼는 java.util.ArrayList가 아닌 java.util.Arrays.ArrayList 이며 동일한 배열을 참조하므로 List 래핑 된 배열에 더 많은 요소를 추가하면 영향을받습니다. 원래 하나도 있고 우리는 길이를 변경할 수 없습니다.
-
ArrayList에는 오버로드 된 생성자가 있습니다.
public ArrayList ()-// 기본 용량이 10 인 arraylist를 반환합니다.
public ArrayList (컬렉션 c)
public ArrayList (int initialCapacity)
-
따라서 Arrays.asList 반환 객체 즉 List (AbstractList)를 위의 두 번째 생성자에 전달하면 새 동적 배열이 생성됩니다 (이 배열 크기는 용량보다 더 많은 요소를 추가함에 따라 증가하고 새 요소는 원래 배열에 영향을주지 않습니다. ) 원본 배열의 얕은 복사 ( 얕은 복사 는 참조에 대해서만 복사하고 원래 배열 에서와 동일한 객체의 새 세트를 생성하지 않음을 의미)
답변
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’에 적용되지 않습니다.
기존 배열 / 목록에 요소를 추가하려고하면 “Exception in thread”main “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 객체에서 변경 한 사항 (배열 목록에서 요소를 추가하거나 제거하는 방법)은 원래 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
답변
우선 Arrays 클래스는 no를 포함하는 유틸리티 클래스입니다. Arrays에서 작동하는 유틸리티 메서드 (Arrays 클래스 덕분에 그렇지 않으면 Array 개체에서 작동하는 자체 메서드를 만들어야 했음)
asList () 메서드 :
asList
메소드는Array
클래스 의 유틸리티 메소드 중 하나 이며 정적 메소드이므로 클래스 이름으로이 메소드를 호출 할 수 있습니다 (예Arrays.asList(T...a)
🙂- 이제 여기에 비틀기가 있습니다.이 메서드는 새
ArrayList
객체를 생성하지 않고 기존Array
객체에 대한 List 참조 만 반환 합니다 (이제asList
메서드 를 사용한 후 기존Array
객체에 대한 두 참조 가 생성됨). - 이것이 그 이유입니다.
List
object에서 작동하는 모든 메서드가List
참조를 사용하여이 Array 객체에서 작동하지 않을 수 있습니다. 예를 들어Array
s 크기가 길이가 고정되어 있으므로이 참조를Array
사용하여 객체 에서 요소를 추가하거나 제거 할 수 없습니다List
(예 :list.add(10)
또는list.remove(10);
그렇지 않으면 UnsupportedOperationException이 발생합니다.) - 목록 참조를 사용하여 수행하는 모든 변경은 기존
Array
의 객체에 반영됩니다 (목록 참조를 사용하여 기존 배열 객체에서 작업하는 것처럼)
첫 번째 경우에는 새 Arraylist
객체를 생성 합니다 (두 번째 경우에는 기존 Array 객체에 대한 참조 만 생성되지만 새 ArrayList
객체 는 생성되지 않음 ), 이제 두 개의 다른 객체가 하나는 Array
객체이고 다른 하나는 객체이며 ArrayList
둘 사이의 연결이 없습니다 (따라서 변경됨 한 개체가 반영되지로 / 다른 목적으로 영향 (케이스 (2)에 Array
그리고 Arraylist
두 개의 다른 객체)
사례 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));
답변
많은 사람들이 이미 기계적인 세부 사항에 대해 대답 해 왔지만 주목할 가치가 있습니다. 이것은 Java의 잘못된 설계 선택입니다.
Java의 asList
방법은 ” 고정 크기 목록을 반환 합니다 …” 로 문서화되어 있습니다. 결과를 가져 와서 .add
메서드를 호출 하면 UnsupportedOperationException
. 이것은 직관적이지 않은 행동입니다! 메소드가를 반환한다고 말하면 List
인터페이스의 메소드를 지원하는 객체를 반환하는 것이 표준 기대치입니다 List
. 개발자는 실제로 모든 메서드를 지원하지 않는 s를 생성 하는 수많은 util.List
메서드 를 기억할 List
필요가 없습니다 List
.
그들이 방법의 이름을 지정했다면 asImmutableList
그것은 의미가 있습니다. 또는 메서드가 실제 값을 반환 List
하고 백업 배열을 복사하면 의미가 있습니다. 그들은 최소한의 놀라움의 원칙과 s 를 피하는 좋은 OO 관행을 위반하는 대신 런타임 성능 과 짧은 이름을 모두 선호하기로 결정했습니다 UnsupportedOperationException
.
(또한 디자이너 interface ImmutableList
는 과다한 UnsupportedOperationException
s 를 피하기 위해를 만들었을 수 있습니다 .)