Arrays.asList (array)와 새로운 ArrayList의 차이점(Arrays.asList (배열))
차이점은 무엇입니까
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
Note that, in Java 8, 'ia' above must be Integer[] and not int[]. Arrays.asList() of an int array returns a list with a single element. When using OP's code snippet, the compiler will catch the issue, but some methods (e.g. Collections.shuffle()) will silently fail to do what you expect.
First of all Arrays class is an utility class which contains no. of utility methods to operate on Arrays (thanks to Arrays class otherwise we would have needed to create our own methods to act on Array objects)
asList() method:
asList
method is one of the utility methods ofArray
class ,it is static method thats why we can call this method by its class name (likeArrays.asList(T...a)
)- Now here is the twist, please note that this method doesn't create new
ArrayList
object, it just returns a List reference to existingArray
object(so now after usingasList
method, two references to existingArray
object gets created) - and this is the reason, all methods that operate on
List
object , may NOT work on this Array object usingList
reference like for example,Array
s size is fixed in length, hence you obviously can not add or remove elements fromArray
object using thisList
reference (likelist.add(10)
orlist.remove(10);
else it will throw UnsupportedOperationException) - any change you are doing using list reference will be reflected in exiting
Array
s object ( as you are operating on existing Array object by using list reference)
In first case you are creating a new Arraylist
object (in 2nd case only reference to existing Array object is created but not a new ArrayList
object) ,so now there are two different objects one is Array
object and another is ArrayList
object and no connection between them ( so changes in one object will not be reflected/affected in another object ( that is in case 2 Array
and Arraylist
are two different objects)
case 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));
case 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));
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());
}
}
}
Arrays.asList()
this method returns its own implementation of List.It takes an array as an argument and builds methods and attributes on top of it, since it is not copying any data from an array but using the original array this causes alteration in original array when you modify list returned by the Arrays.asList()
method.
on the other hand.
ArrayList(Arrays.asList());
is a constructor of ArrayList
class which takes a list as argument and returns an ArrayList
that is independent of list ie. Arrays.asList()
in this case passed as an argument. that is why you see these results;
Many people have answered the mechanical details already, but it's worth noting: This is a poor design choice, by Java.
Java's asList
method is documented as "Returns a fixed-size list...". If you take its result and call (say) the .add
method, it throws an UnsupportedOperationException
. This is unintuitive behavior! If a method says it returns a List
, the standard expectation is that it returns an object which supports the methods of interface List
. A developer shouldn't have to memorize which of the umpteen util.List
methods create List
s that don't actually support all the List
methods.
If they had named the method asImmutableList
, it would make sense. Or if they just had the method return an actual List
(and copy the backing array), it would make sense. They decided to favor both runtime-performance and short names, at the expense of violating both the Principle of Least Surprise and the good-O.O. practice of avoiding UnsupportedOperationException
s.
(Also, the designers might have made a interface ImmutableList
, to avoid a plethora of UnsupportedOperationException
s.)
1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); //copy
2.List<Integer> list2 = Arrays.asList(ia);
In line 2, Arrays.asList(ia)
returns a List
reference of inner class object defined within Arrays
, which is also called ArrayList
but is private and only extends AbstractList
. This means what returned from Arrays.asList(ia)
is a class object different from what you get from new ArrayList<Integer>
.
You cannot use some operations to line 2 because the inner private class within Arrays
does not provide those methods.
Take a look at this link and see what you can do with the private inner class: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Arrays.java#Arrays.ArrayList
Line 1 creates a new ArrayList
object copying elements from what you get from line 2. So you can do whatever you want since java.util.ArrayList
provides all those methods.
Summary of difference -
when list is created without using new operator Arrays.asList() method it return Wrapper which means
1. you can perform add/update Operation.
2. the changes done in original array will be reflected to List as well and vice versa.
In response to some comments asking questions about the behaviour of Arrays.asList() since Java 8:
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);
'Programming' 카테고리의 다른 글
Django-DB-Migrations : 보류중인 트리거 이벤트가 있으므로 ALTER TABLE을 사용할 수 없습니다. (0) | 2020.08.18 |
---|---|
Active Directory에서 사용자 목록을 얻으려면 어떻게해야합니까? (0) | 2020.08.18 |
안드로이드 응용 프로그램이 전경에 있는지 확인하십시오. (0) | 2020.08.18 |
split () 결과에 빈 문자열이 반환되는 이유는 무엇입니까? (0) | 2020.08.18 |
* 정적 일 수있는 * C # 메서드는 정적이어야합니까? (0) | 2020.08.17 |