Programming

Arrays.asList (array)와 새로운 ArrayList의 차이점

procodes 2020. 8. 18. 19:17
반응형

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

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

    Arrays.asList(ia)
    

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

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

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

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

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

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


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:

  1. asList method is one of the utility methods of Array class ,it is static method thats why we can call this method by its class name (like Arrays.asList(T...a) )
  2. Now here is the twist, please note that this method doesn't create new ArrayList object, it just returns a List reference to existing Array object(so now after using asList method, two references to existing Array object gets created)
  3. and this is the reason, all methods that operate on List object , may NOT work on this Array object using List reference like for example, Arrays size is fixed in length, hence you obviously can not add or remove elements from Array object using this List reference (like list.add(10) or list.remove(10); else it will throw UnsupportedOperationException)
  4. any change you are doing using list reference will be reflected in exiting Arrays 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 Lists 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 UnsupportedOperationExceptions.

(Also, the designers might have made a interface ImmutableList, to avoid a plethora of UnsupportedOperationExceptions.)


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

참고URL : https://stackoverflow.com/questions/16748030/difference-between-arrays-aslistarray-and-new-arraylistintegerarrays-aslist

반응형