[java] List.of와 Arrays.asList의 차이점은 무엇입니까?

Java 9는 목록에 대한 새로운 팩토리 메소드를 도입했습니다 List.of.

List<String> strings = List.of("first", "second");

이전 옵션과 새 옵션의 차이점은 무엇입니까? 즉, 이것의 차이점은 무엇입니까?

Arrays.asList(1, 2, 3);

이:

List.of(1, 2, 3);



답변

Arrays.asList에서 반환 된 목록 List.of변경 불가능한 동안 변경 가능한 목록을 반환합니다 .

List<Integer> list = Arrays.asList(1, 2, null);
list.set(1, 10); // OK

List<Integer> list = List.of(1, 2, 3);
list.set(1, 10); // Fails with UnsupportedOperationException

Arrays.asList다음을 List.of수행하지 않는 동안 null 요소를 허용합니다 .

List<Integer> list = Arrays.asList(1, 2, null); // OK
List<Integer> list = List.of(1, 2, null); // Fails with NullPointerException

contains null과 다르게 동작합니다.

List<Integer> list = Arrays.asList(1, 2, 3);
list.contains(null); // Returns false

List<Integer> list = List.of(1, 2, 3);
list.contains(null); // Fails with NullPointerException

Arrays.asList전달 된 배열의보기를 반환하므로 배열의 변경 사항도 목록에 반영됩니다. 들어 List.of이 사실이 아니다 :

Integer[] array = {1,2,3};
List<Integer> list = Arrays.asList(array);
array[1] = 10;
System.out.println(list); // Prints [1, 10, 3]

Integer[] array = {1,2,3};
List<Integer> list = List.of(array);
array[1] = 10;
System.out.println(list); // Prints [1, 2, 3]


답변

사이의 차이 Arrays.asListList.of

JavaDocs 및 Stuart Marks (또는 이전 버전) 의이 강연 을 참조하십시오 .

코드 예제로 다음을 사용하겠습니다.

List<Integer> listOf = List.of(...);
List<Integer> asList = Arrays.asList(...);
List<Integer> unmodif = Collections.unmodifiableList(asList);

구조적 불변성 (또는 : 수정 불가능)

구조적으로 변경 하려는 시도 List.ofUnsupportedOperationException. 여기에는 추가 , 설정제거 와 같은 작업이 포함됩니다 . 그러나 목록에있는 개체의 내용을 변경할 수 있으므로 (개체가 변경 불가능하지 않은 경우) 목록이 “완전히 변경 불가능”하지 않습니다.

로 생성 된 수정 불가능한 목록의 운명과 동일 Collections.unmodifiableList합니다. 이 목록 만 원래 목록 보기 이므로 원래 목록을 변경하면 변경 될 수 있습니다.

Arrays.asList완전히 변경할 수 없으며에 대한 제한이 없습니다 set.

listOf.set(1, "a");  // UnsupportedOperationException
unmodif.set(1, "a"); // UnsupportedOperationException
asList.set(1, "a");  // modified unmodif! unmodif is not truly unmodifiable

마찬가지로 백업 배열을 변경하면 (보유하고있는 경우) 목록이 변경됩니다.

구조적 불변성은이 답변의 범위를 벗어난 방어 코딩, 동시성 및 보안과 관련된 많은 부작용을 동반합니다.

무적의 적대감

List.ofJava 1.5 이후의 모든 컬렉션 null은 요소로 허용되지 않습니다 . null요소 또는 조회 로 전달하려고 시도 하면 NullPointerException.

이후 Arrays.asList1.2에서 컬렉션 (컬렉션 프레임 워크), 그것이 허용 null들.

listOf.contains(null);  // NullPointerException
unmodif.contains(null); // allowed
asList.contains(null);  // allowed

직렬화 된 형식

때문에 List.of자바 (9) 도입 및이 방법에 의해 생성 된리스트는 자신의 (바이너리) 직렬화 된 형식을 가지고있다, 그들은 이전 JDK 버전 (NO 역 직렬화 할 수없는 바이너리 호환성 ). 그러나 예를 들어 JSON을 사용하여 역 직렬화 할 수 있습니다.

정체

Arrays.asList내부적으로를 호출 new ArrayList하여 참조 부등식을 보장합니다.

List.of내부 구현에 따라 다릅니다. 반환 된 인스턴스는 참조 동등성을 가질 수 있지만 이것이 보장되지 않으므로 신뢰할 수 없습니다.

asList1 == asList2; // false
listOf1 == listOf2; // true or false

목록 List.equals이 생성 된 방법이나 지원하는 작업에 관계없이 동일한 순서로 동일한 요소를 포함하는 경우 목록은 동일합니다 (를 통해 ).

asList.equals(listOf); // true i.f.f. same elements in same order

구현 (경고 : 세부 정보는 버전에 따라 변경 될 수 있음)

목록의 요소 수가 List.of2 개 이하인 경우 요소는 특수 (내부) 클래스의 필드에 저장됩니다. 예는 2 개의 요소 (부분 소스)를 저장하는 목록입니다.

static final class List2<E> extends AbstractImmutableList<E> {
    private final E e0;
    private final E e1;

    List2(E e0, E e1) {
        this.e0 = Objects.requireNonNull(e0);
        this.e1 = Objects.requireNonNull(e1);
    }
}

그렇지 않으면 .NET과 유사한 방식으로 배열에 저장됩니다 Arrays.asList.

시간 및 공간 효율성

List.of필드 기반 (크기 <2)이다 구현은 어떤 작업이 약간 빠르게 수행한다. 예를 들어, size()배열 길이를 가져 오지 않고 상수를 반환 할 수 contains(E e)있으며 반복 오버 헤드가 필요하지 않습니다.

를 통해 수정할 수없는 목록을 생성 List.of하는 것도 더 빠릅니다. 위의 생성자를 2 개의 참조 할당 (임의의 요소에 대한 할당 포함)과 비교하여

Collections.unmodifiableList(Arrays.asList(...));

2 개의 목록과 다른 오버 헤드를 생성합니다. 공간 측면에서 UnmodifiableList래퍼와 약간의 동전 을 절약합니다 . 궁극적으로 HashSet동등한 비용 절감 이 더 설득력이 있습니다.


결론 시간 : List.of변경되지 않는 Arrays.asList목록을 원할 때 와 변경할 수있는 목록을 원할 때 사용합니다 (위 그림 참조).


답변

List.ofArrays.asList 의 차이점을 요약 해 보겠습니다.

  1. List.of데이터 세트가 적고 변경되지 않은 Arrays.asList경우 가장 잘 사용할 수있는 반면, 크고 동적 데이터 세트의 경우 가장 잘 사용할 수 있습니다.

  2. List.of필드 기반 구현이 있기 때문에 오버 헤드 공간을 매우 적게 차지하고 고정 오버 헤드와 요소 별 기준 모두에서 더 적은 힙 공간을 사용합니다. Arrays.asList초기화하는 동안 힙에 더 많은 객체를 생성하기 때문에 더 많은 오버 헤드 공간 을 차지합니다.

  3. 에서 반환 된 컬렉션 List.of은 변경 불가능하므로 스레드로부터 안전하지만에서 반환 된 컬렉션 Arrays.asList은 변경 가능하며 스레드로부터 안전하지 않습니다. (불변 컬렉션 인스턴스는 일반적으로 가변 인스턴스보다 훨씬 적은 메모리를 사용합니다.)

  4. List.of허용하지 않는 동안 요소를 Arrays.asList허용 널 (null) 요소를.


답변

외에도 위의 답변에서 두 가지 모두에 대해 특정 작업이 있습니다 List::of와는 Arrays::asList차이가 :

+----------------------+---------------+----------+----------------+---------------------+
|      Operations      | SINGLETONLIST | LIST::OF | ARRAYS::ASLIST | JAVA.UTIL.ARRAYLIST |
+----------------------+---------------+----------+----------------+---------------------+
|          add         |             |       |              |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|        addAll        |             |       |              |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|         clear        |             |       |              |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|        remove        |             |       |              |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|       removeAll      |       ❗️       |        |        ❗️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|       retainAll      |       ❗️       |       |        ❗️        |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|      replaceAll      |             |       |        ✔️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|          set         |             |       |        ✔️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|         sort         |       ✔️       |        |        ✔️      |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
|  remove on iterator  |             |       |              |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
| set on list-iterator |             |       |        ✔️       |          ✔️          |
+----------------------+---------------+----------+----------------+---------------------+
  1. ✔️ 방법이 지원됨을 의미합니다.
  2. ❌는이 메서드를 호출하면 UnsupportedOperationException이 발생 함을 의미합니다.
  3. ❗️는 메서드의 인수가 변이를 일으키지 않는 경우에만 메서드가 지원됨을 의미합니다. 예를 들어 Collections.singletonList ( “foo”). retainAll ( “foo”)은 괜찮지 만 Collections.singletonList ( “foo”). retainAll ( “bar”) ) UnsupportedOperationException 발생

Collections :: singletonList Vs 에 대한 추가 정보 목록 ::의


답변