[Java] Arrays.asList() vs. List.of()

CJY·2023년 7월 18일
0

Java

목록 보기
1/1

Arrays.asList()와 List.of()

자바에서 보통 List로 변환하기 위해서는 Arrays.asList(array)를 사용합니다.

Java 9 버전 부터는 List.of(array)라는 새로운 팩토리 메소드가 있습니다.

이 둘의 차이점은 무엇일까 ? 어떤걸 사용하면 될까 ?

라는 고민을 시작으로 글을 작성했습니다.

변경 가능 여부 (Mutable / Immutable)

Arrays.asList()에서 반환된 List는 변경이 가능합니다.

하지만, List.of()에서 반환된 List는 변경이 불가능합니다.

대표적으로 set() 메서드를 사용해보면 둘의 차이를 알 수 있습니다.

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()는 ArrayList를 반환하고, set() 메서드가 구현돼 있습니다.
(Arrays 내부 클래스 ArrayList)

(참고) Arrays.asList()가 반환하는 ArrayList 타입은 java.util.ArrayList가 가 아니라 Arrays 내부 클래스입니다. add()와 remove() 메서드는 구현되어 있지 않아서, 배열의 크기 변동과 관련된 행동은 할 수 없습니다.

반면, List.of()ListN이라는 타입의 객체를 반환하는데, 이는 불변 객체(Immutable object)입니다. 따라서 수정할 수 없습니다.

null 체크

Array.asList()는 null을 허용합니다.

List.of()를 호출하면, 내부에서 넘겨 받은 파라미터들에 대해 null체크를 하고 null 파라미터에 대해 예외를 발생시킵니다.

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

List.of()로 반환된 객체의 contains() 메서드에서도 넘겨 받은 파라미터에 대해 null체크를 하고, null이라면 NPE(Null pointer exception)이 발생합니다.

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(array)의 객체로 add()remove()를 사용할 수 없는 이유는 참조를 넘겨 받기 때문입니다. 따라서 배열의 크기를 늘리거나 줄일 수 없습니다.

Arrays.asList(array)는 참조를 넘겨주기 때문에 original 배열의 값이 변경되면 새로 할당한 변수 newPointer에도 영향이 갑니다.

Integer[] original = {1,2};
List<Integer> newPointer = Arrays.asList(original);
original[0] = 100;
System.out.println(newPointer); // [100, 2]

반대로 newPointerset()으로 원소를 변경하면 original에도 영향이 가는건 당연하겠죠.

List.of(original)의 결과는 값을 기반으로 독립적인 객체를 만들기 때문에 참조가 일어나지 않습니다.

Integer[] original = {1,2};
List<Integer> list = List.of(original);
original[0] = 100;
System.out.println(list); // [1, 2]

메모리 사용 측면

Arrays.asList()List.of()보다 힙에 더 많은 개체를 생성하기 때문에 더 많은 오버헤드 공간을 차지합니다. 따라서, 단지 값 요소가 필요한 경우라면 List.of()가 적합합니다.

상황 예시

예를 들어, Array를 ArrayList 또는 HashSet 등으로 변환하고 싶은데 참조나 변경 가능 여부는 상관없고 기존 요소만 알면 되는 상황입니다. 이 때는 List.of()가 적합합니다.

List<String> list = new ArrayList<>(List.of(array));
Set<String> set = new HashSet<>(List.of(array));

요약

위에서 언급한 내용을 종합해서 정리한 내용은 다음과 같습니다.

  • Arrays.asList()는 크고 동적인 데이터에 사용하고, List.of()는 작고 변경되지 않는 데이터의 경우 사용합니다.
  • List.of()는 필드 기반 구현이 있고, 비교적 힙 공간을 덜 사용하기에 요소 자체가 필요하다면 List.of()가 적절합니다.
  • Arrays.asList()는 변경이 가능하기 때문에 thread safety 하지 않고, List.of()는 불변객체이므로 thread safety합니다.
  • Arrays.asList()는 null 요소를 허용하고 List.of()는 null 요소를 허용하지 않습니다.
  • Arrays.asList(), List.of() 모두 크기는 변경할 수 없습니다. 크기를 바꾸려면 Collections을 생성해서 요소의 값을 옮겨야 합니다.

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

profile
열심히 성장 중인 백엔드

2개의 댓글

comment-user-thumbnail
2023년 7월 18일

소중한 정보 잘 봤습니다!

1개의 답글