불변 리스트를 만들기 위해서 나는 주로 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 |