Immutable List

Jeonghwa·2023년 1월 17일
0

Immutable List란

Immutable의 사전적 의미로 불변의, 변경할 수 없는 이라는 뜻이다. 즉 Immutable List는 수정(추가, 삭제, 변경)이 불가능한 List이며, 컬렉션이 생성된 후 변경되는 것을 방지할 때 사용할 수 있다.


Immutable List가 아닌 경우

final
final은 불변이 아닌 재할당을 금지하는 키워드이다. 따라서 list의 원소들을 변경할 수 있으며, 단지 다른 list로 재할당 할 수 없다.

  final List<Integer> list = new ArrayList<>();
  list.add(1);
  list = new ArrayList<String>(); // 컴파일 에러

참고 : docs.oracle - final Variables

Arrays.asList()
Arrays.asList()는 고정된 사이즈의 List를 반환하기 때문에 add나 remove를 호출하면 UnsupportedOperationException이 발생한다. 하지만 원소의 변경은 가능하다.

  List<Integer> list = Arrays.asList(1, 2, 3);
  list.set(1, 10);
  try {
      list.add(1);
  }
  catch (UnsupportedOperationException e){
          System.out.println("UnsupportedOperationException 발생");
  }

참고 : docs.oracle - class Arrays


Immutable List (Java 8)

Collections.unmodifiableList()
Collections.unmodifiableList()는 읽기 전용 리스트를 반환하며 이는 List의 수정이 불가능하다. (UnsupportedOperationException 발생)

  List<Integer> list = new ArrayList<>();
  list.add(1);
  List<Integer> unmodifiableList = Collections.unmodifiableList(list);
  try {
      unmodifiableList.add(2);
  }
  catch (UnsupportedOperationException e){
      System.out.println("UnsupportedOperationException 발생");
  }

원래 참조하고 있는 list의 수정은 막을 수 없다는 한계가 있지만, 참조변수에 재할당을 해버리면 수정할 수 없다.

List<Integer> list = new ArrayList<>();
list.add(1);
list = Collections.unmodifiableList(list);

Immutable List (Java 9이상)

자바9부터 List, Set, Map 인터페이스에 Immutable Collection을 만들 수 있는 메서드 of가 추가되었다. 그리고 of메서드를 활용해 만들어진 컬렉션은 Null value를 허용하지 않는다. (Map.of의 경우 key,value 둘다 Null을 허용하지 않음)

List.of()
List.of(e1)
List.of(e1, e2)         // fixed-argument form overloads up to 10 elements
List.of(elements...)   // varargs form supports an arbitrary number of elements or an array
Set.of()
Set.of(e1)
Set.of(e1, e2)         // fixed-argument form overloads up to 10 elements
Set.of(elements...)   // varargs form supports an arbitrary number of elements or an array
Map.of()
Map.of(k1, v1)
Map.of(k1, v1, k2, v2)    // fixed-argument form overloads up to 10 key-value pairs
Map.ofEntries(entry(k1, v1), entry(k2, v2),...) // varargs form supports an arbitrary number of Entry objects or an array

사용법

  List<Integer> list = List.of(1,2,3);
  try {
      list.add(4);
  }
  catch (UnsupportedOperationException e){
      System.out.println("UnsupportedOperationException 발생");
  }
  Set<Integer> set = Set.of(1,2,3);
  Map<Integer, String> map = Map.of(1,"hi",2,"bye");

Immutable List(Collection)의 장점

장점1
변경할 수 없는 Collection의 장점은 자동으로 스레드로부터 안전하다는 것이다. 컬렉션을 만든 후 여러 스레드에 전달할 수 있으며 모두 일관적으로 Read할 수 있다.

하지만 불변컬렉션불변객체의 컬렉션은 다르다는 것을 주의해야한다. 즉, 불변컬렉션에 수정가능한 원소(객체)가 포함된 경우 일관되게 동작하지 않거나 내용이 변경된 것 처럼 보일 수 있다.

예시

List<Integer> list1 = Arrays.asList(1,2,3);
List<Integer> list2 = new ArrayList<>(list1); // list1의 복사본

// 변경할 수 없는 list 생성
List<List<Integer>> immutableList1 = List.of(list1,list1);
List<List<Integer>> immutableList2 = List.of(list2,list2);
System.out.println(immutableList1.equals(immutableList2)); // true

// 원본 list1 수정
list1.set(1,10);

// 더이상 immutableList1과 immutableList2는 동일하지 않다.
System.out.println(immutableList1.equals(immutableList2)); // false

장점2
사이즈가 변할 일이 없기 때문에 훨씬 더 공간 효율적으로 사용가능하며, 메모리상에 최적화되어있다.
arrayList같은 경우 default size가 존재하며 원소가 추가될 경우 새로운 array생성 및 복사가 일어난다. 하지만 immutable List는 변하지 않기때문에 깔끔하게 사용가능하다.

참고 : docs.oracle - Creating Immutable Lists, Sets, and Maps

profile
backend-developer🔥

0개의 댓글