Arrays.asList (array)와 new ArrayList <Integer> (Arrays.asList (array))의 차이점


119

차이점은 무엇입니까

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));

2
Google Guava의 옵션 을 돌보는 것이 좋습니다 . Lists.newArrayList(ia)첫 번째 옵션과 마찬가지로 독립 사본을 만듭니다. 단순히 더 일반적이고 보는 것이 좋습니다.
qben 2014 년

답변:


228
  1. 먼저 이것이 무엇을하는지 봅시다 :

    Arrays.asList(ia)

    배열을 취하고 ia를 구현하는 래퍼 List<Integer>를 만들어 원래 배열을 목록으로 사용할 수 있도록합니다. 아무것도 복사되지 않고 모두 하나의 래퍼 개체 만 만들어집니다. 목록 래퍼에 대한 작업은 원래 배열로 전파됩니다. 즉, 목록 래퍼를 섞으면 원래 배열도 섞이고 요소를 덮어 쓰면 원래 배열에서 덮어 쓰게됩니다. 물론 일부List 래퍼에서 추가 또는 추가와 같은 작업은 허용되지 않습니다. 목록에서 요소를 제거하면 요소를 읽거나 덮어 쓸 수만 있습니다.

    목록 래퍼는 확장되지 않으며 ArrayList다른 종류의 개체입니다. ArrayLists에는 요소를 저장하고 내부 배열의 크기를 조정할 수있는 자체 내부 배열이 있습니다. 래퍼에는 자체 내부 배열이 없으며 주어진 배열로 작업을 전파 할뿐입니다.

  2. 반면에 다음과 같이 새 어레이를 생성하면

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

    그런 다음 ArrayList원본과 완전히 독립적 인 복사 본인 new를 만듭니다 . 여기서도 사용하여 래퍼를 만들지 Arrays.asList만 새 구성 중에 만 사용되며 ArrayList나중에 가비지 수집됩니다. 이 새로운 구조 ArrayList는 원래 배열과 완전히 독립적입니다. 동일한 요소 (원래 배열과이 새로운 ArrayList참조 모두 메모리에서 동일한 정수를 참조)를 포함하지만 참조를 보유하는 새로운 내부 배열을 만듭니다. 따라서 셔플, 요소 추가, 제거 등을 할 때 원래 배열은 변경되지 않습니다.


9
@Dineshkumar 래퍼는 클래스의 한 인터페이스를 다른 인터페이스로 변환하는 디자인 패턴입니다. 참조 래퍼 패턴의 기사를. | 어디서 업 캐스트해야합니까? List<Integer>변수 유형 (또는 메서드 인수 등) 에 사용 하는 것이 좋습니다 . 이렇게하면 코드가보다 일반화되고 List많은 코드를 다시 작성하지 않고도 필요에 따라 다른 구현으로 쉽게 전환 할 수 있습니다 .
Petr Pudlák 2013 년

좋은 설명입니다. 이 질문을 확장하면 Arrays.asList () 메서드도 varargs를 사용합니다. 특정 값을 전달하면 Arrays.asList (1,3,5) 두 번, 동일한 목록을 반환합니까?
분에

27

ArrayList결과 결과 Arrays.asList()가 유형 이 아니기 때문 java.util.ArrayList입니다. Arrays.asList()생성 ArrayList유형의 java.util.Arrays$ArrayList확장하지 않는이 java.util.ArrayList있지만 확장java.util.AbstractList


9
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);

4

나는 여기에 꽤 늦었지만 어쨌든 문서 참조가있는 설명이 답을 찾는 사람에게 더 좋을 것이라고 느꼈습니다.

  1. java.util.Arrays
  • 이것은 주어진 배열에서 작동하는 여러 정적 메소드가있는 유틸리티 클래스입니다.
  • asList 는 입력 배열을 취하고 List 인터페이스를 구현하는 AbstractList를 확장하는 정적 중첩 클래스 인 java.util.Arrays.ArrayList 의 객체를 반환하는 정적 메서드 중 하나 입니다.
  • 따라서 Arrays.asList (inarray)는 입력 배열 주위에 List 래퍼를 반환하지만이 래퍼는 java.util.ArrayList가 아닌 java.util.Arrays.ArrayList 이며 동일한 배열을 참조하므로 List 래핑 된 배열에 더 많은 요소를 추가하면 영향을받습니다. 원래 하나도 있고 우리는 길이를 변경할 수 없습니다.
  1. java.util.ArrayList
  • ArrayList에는 오버로드 된 생성자가 있습니다.

    public ArrayList ()-// 기본 용량이 10 인 arraylist를 반환합니다.

    public ArrayList (컬렉션 c)

    public ArrayList (int initialCapacity)

  • 따라서 Arrays.asList 반환 객체 즉 List (AbstractList)를 위의 두 번째 생성자에 전달하면 새 동적 배열이 생성됩니다 (이 배열 크기는 용량보다 더 많은 요소를 추가함에 따라 증가하고 새 요소는 원래 배열에 영향을주지 않습니다. ) 원본 배열의 얕은 복사 ( 얕은 복사 는 참조에 대해서만 복사하고 원래 배열 에서와 동일한 객체의 새 세트를 생성하지 않음을 의미)


4
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

3

우선 Arrays 클래스는 no를 포함하는 유틸리티 클래스입니다. Arrays에서 작동하는 유틸리티 메서드 (Arrays 클래스 덕분에 그렇지 않으면 Array 개체에서 작동하는 자체 메서드를 만들어야 했음)

asList () 메서드 :

  1. asList메소드는 Array클래스 의 유틸리티 메소드 중 하나 이며 정적 메소드이므로 클래스 이름으로이 메소드를 호출 할 수 있습니다 (예 Arrays.asList(T...a):)
  2. 이제 여기에 비틀기가 있습니다.이 메서드는 새 ArrayList객체를 생성하지 않고 기존 Array객체에 대한 List 참조 만 반환 합니다 (이제 asList메서드 를 사용한 후 기존 Array객체에 대한 두 참조 가 생성됨).
  3. 이것이 그 이유입니다. Listobject에서 작동하는 모든 메서드가 List참조를 사용하여이 Array 객체에서 작동하지 않을 수 있습니다. 예를 들어 Arrays 크기가 길이가 고정되어 있으므로이 참조를 Array사용하여 객체 에서 요소를 추가하거나 제거 할 수 없습니다 List(예 : list.add(10)또는 list.remove(10);그렇지 않으면 UnsupportedOperationException이 발생합니다.)
  4. 목록 참조를 사용하여 수행하는 모든 변경은 기존 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));

3

많은 사람들이 이미 기계적인 세부 사항에 대해 대답 해 왔지만 주목할 가치가 있습니다. 이것은 Java의 잘못된 설계 선택입니다.

Java의 asList방법은 " 고정 크기 목록을 반환 합니다 ..." 로 문서화되어 있습니다. 결과를 가져 와서 .add메서드를 호출 하면 UnsupportedOperationException. 이것은 직관적이지 않은 행동입니다! 메소드가를 반환한다고 말하면 List인터페이스의 메소드를 지원하는 객체를 반환하는 것이 표준 기대치입니다 List. 개발자는 실제로 모든 메서드를 지원하지 않는 s를 생성 하는 수많은 util.List메서드 를 기억할 List필요가 없습니다 List.

그들이 방법의 이름을 지정했다면 asImmutableList그것은 의미가 있습니다. 또는 메서드가 실제 값을 반환 List하고 백업 배열을 복사하면 의미가 있습니다. 그들은 최소한의 놀라움의 원칙과 s 를 피하는 좋은 OO 관행을 위반하는 대신 런타임 성능 짧은 이름을 모두 선호하기로 결정했습니다 UnsupportedOperationException.

(또한 디자이너 interface ImmutableList는 과다한 UnsupportedOperationExceptions 를 피하기 위해를 만들었을 수 있습니다 .)


2

Java 8에서 위의 'ia'는 int []가 아니라 Integer [] 여야합니다. int 배열의 Arrays.asList ()는 단일 요소가있는 목록을 반환합니다. OP의 코드 스 니펫을 사용할 때 컴파일러는 문제를 포착하지만 일부 메소드 (예 : Collections.shuffle ())는 예상 한대로 작동하지 않습니다.


1
나는 ArrayList <Integer> al = new ArrayList <Integer> (Arrays.asList (a)); 할 때이 컴파일러 문제에 직면했습니다. a는 int []입니다. 내 al은 인쇄했을 때 쓰레기처럼 보이는 단일 요소를 얻었습니다. 그 요소는 무엇입니까? 그리고 거기에 어떻게됩니까? 나는 자바 7에서이 문제를 직면
Jyotsana Nandwani에게

@JyotsanaNandwani Pls는 내 대답을 확인합니다 : stackoverflow.com/a/54105519/1163607
NINCOMPOOP

1
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

Arrays.asList()

이 메소드는 List의 자체 구현을 반환합니다. 배열에서 데이터를 복사하지 않고 원래 배열을 사용하기 때문에 배열을 인수로 사용하고 그 위에 메소드와 속성을 빌드하므로 수정할 때 원래 배열이 변경됩니다. 에 의해 반환 된 목록 Arrays.asList() 메서드에서 입니다.

반면에. 목록을 인수로 취하고 목록 에 독립적 인을 반환하는 클래스
ArrayList(Arrays.asList()); 의 생성자입니다 . 이 경우 인수로 전달됩니다. 이것이 바로 이러한 결과를 보는 이유입니다.ArrayListArrayListArrays.asList()


0
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하지만 private이며 AbstractList. 이것은 반환 Arrays.asList(ia)되는 것이 당신이 얻은 것과 다른 클래스 객체 임을 의미합니다.new ArrayList<Integer> .

내부 개인 클래스가 내부에 있기 때문에 2 행에 일부 작업을 사용할 수 없습니다. Arrays 가 해당 메소드를 제공하지 .

이 링크를 살펴보고 개인 내부 클래스로 수행 할 수있는 작업을 확인하십시오. http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ Arrays.java # Arrays.ArrayList

1 ArrayList행은 2 행에서 얻은 요소를 복사 하는 새 객체를 만듭니다 . 따라서 java.util.ArrayList이러한 모든 메서드를 제공 하므로 원하는 모든 작업을 수행 할 수 있습니다 .


0

차이점 요약-

새 연산자 Arrays.asList () 메서드를 사용하지 않고 목록을 만들면 Wrapper를 반환합니다.

1. 추가 / 업데이트 작업을 수행 할 수 있습니다.

2. 원래 배열에서 수행 된 변경 사항은 List에도 반영되며 그 반대의 경우도 마찬가지입니다.


0

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);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.