본문 바로가기

Java

List.of() vs Arrays.asList() vs Collections.unmodifiableList()

불변 리스트를 만들기 위해서 나는 주로 Arrays.asList를 사용해왔다.

자바에는 불변 리스트를 만드는 방법이 여러가진데, 이들의 차이점은 무엇일까?

 

 

1. 셋 다 불변 리스트이다. 하지만 조금씩 허점이 있다.

List.of 는 완전한 불변 리스트이다. add, set, remove 에 대해서 모두 UnsupportedOerationException을 발생시킨다.

UnsupportedOerationException 은 RuntimeException 을 상속하는 unchecked 예외이다.

 

하지만 Arrays.asList 는 add, remove 는 같은 예외를 던지지만, set 이 가능하다.

따라서 정확하게는 반만 불변이다.

 

Collections.unmodifiableList 는 List.of처럼 불변 리스트지만, 원본배열을 참조하기 때문에 원본배열이 바뀌면 값이 바뀐다.

 

다음의 세개의 리스트를 사용해보자.

List<Integer> list1 = List.of(1,2,3);

List<Integer> list2 = Arrays.asList(1,2,3);

List<Integer> list3 = Collections.unmodifiableList(list2);
        list1.set(0, 3); // UnsupportedOperationException
        list2.set(0, 3); // 가능
        list3.set(0, 3); // UnsupportedOperationException

        list1.add(1); // UnsupportedOperationException
        list2.add(2); // UnsupportedOperationException
        list3.add(3); // UnsupportedOperationException
        
        System.out.println(list2);
        System.out.println(list3);
        list2.set(0, 7);
        System.out.println(list2);
        System.out.println(list3); // 원본배열을 바꾸자 Collections.unmodifiableList 로 만든 배열도 바뀜

중간에 set과 add는 주석처리하고 실행하면 아래와 같이 원본배열 list2를 사용하는 list3의 허점을 볼 수 있다.

 

 

 

 

3. List.Of() 은 null을 허용하지 않는다. 하지만 Arrays.asList(), Collections.unmodifiableList() 는 허용한다.

따라서 다음과 같은 결과가 나온다.

List<Integer> list1 = Arrays.asList(1, 2, null); // 가능
List<Integer> list2 = Collections.unmodifiableList(list1); // 가능
List<Integer> list3 = List.of(1, 2, null); // NPE 발생

 

 

4. List.Of() 은 contains() 에 null을 허용하지 않는다. 하지만 Arrays.asList(), Collections.unmodifiableList() 는 허용한다.

List<Integer> list1 = Arrays.asList(1, 2, 3);
list1.contains(null); // false 반환

List<Integer> list2 = Collections.unmodifiableList(list1);
list2.contains(null); // false 반환

List<Integer> list3 = List.of(1, 2, 3);
list3.contains(null); // NPE 발생

 

 

 

 

4. List.Of(), Arrays.asList() 는 배열을 인자값으로 줄 수 있는데, List.of 는 원본 배열의 값이 바뀌어도 바뀌지 않지만, Arrays.asList는 원본배열이 바뀌면 같이 바뀐다.

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

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

 

 

 

 

5.Arrays.asList는 내부적으로 new ArrayList를 호출한다. 하지만 List.of는 내부 구현에 따라 다릅니다. 반환 된 인스턴스는 참조가 같을 수  있지만 이것이 보장되지 않으므로 신뢰할 수 없다.

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

 

 

 

 

stackoverflow.com/questions/46579074/what-is-the-difference-between-list-of-and-arrays-aslist

'Java' 카테고리의 다른 글

Java Garbage Collection  (0) 2021.03.15
Enum 활용(람다식 사용하기)  (0) 2020.12.18
함수형 인터페이스 정리  (0) 2020.12.18
인터페이스 vs 추상 클래스  (0) 2020.12.18
JAVA8) 스트림 API  (0) 2020.12.11