컬렉션 유틸

2024. 6. 29. 11:55김영한 Java/컬렉션 프레임워크

컬렉션을 편하게 다룰 수 있는 다양한 기능을 알아보자.

package collection.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsSortMain {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);

        Integer max = Collections.max(list);
        Integer min = Collections.min(list);

        System.out.println("max = " + max);
        System.out.println("min = " + min);

        System.out.println(list);
        Collections.shuffle(list);
        System.out.println("shuffle list = " + list);
        Collections.sort(list);
        System.out.println("sort list = " + list);
        Collections.reverse(list);
        System.out.println("reversed list = " + list);
    }
}

 

실행 결과

max = 5
min = 1
[1, 2, 3, 4, 5]
shuffle list = [2, 5, 1, 4, 3]
sort list = [1, 2, 3, 4, 5]
reversed list = [5, 4, 3, 2, 1]

 

package collection.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ImmutableMain {
    public static void main(String[] args) {
        //불변 리스트 생성
        List<Integer> list = List.of(1, 2, 3);

        //가변 리스트
        ArrayList<Integer> mutableList = new ArrayList<>(list);
        mutableList.add(4);
        System.out.println("mutableList = " + mutableList);
        System.out.println("mutableList.getClass() = "+mutableList.getClass());

        //불변 리스트
        List<Integer> unmodifiableList = Collections.unmodifiableList(mutableList);
        //unmodifiableList.add(4); //예외 발생
        
    }
}

 

실행 결과

mutableList = [1, 2, 3, 4]
mutableList.getClass() = class java.util.ArrayList
  • 불변 리스트를 가변 리스트로 전환하려면 new ArrayList<>()를 사용하면 된다.
  • 가변 리스트를 불변 리스트로 전환하려면 Collections.unmodifiableList()를 사용하면 된다.
    • 물론 다양한 unmodifiableXxx()가 존재한다.

 

 

빈 리스트 생성

package collection.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class EmptyListMain {
    public static void main(String[] args) {
        //빈 가변 리스트 생성
        ArrayList<Integer> list1 = new ArrayList<>();
        LinkedList<Integer> list2 = new LinkedList<>();

        //빈 불변 리스트 생성
        List<Integer> list3 = Collections.emptyList();
        List<Integer> list4 = List.of();

        System.out.println("list3.getClass() = " + list3.getClass());
        System.out.println("list4.getClass() = " + list4.getClass());

    }
}

 

실행 결과

list3.getClass() = class java.util.Collections$EmptyList
list4.getClass() = class java.util.ImmutableCollections$ListN
  • 빈 가변 리스트는 원하는 컬렉션의 구현체를 직접 생성하면 된다.
  • 빈 불변 리스트는 2가지 생성 방법이 있다.
    • Collections.emptyList() : 자바5부터 제공되는 기능이다.
    • List.of() : 자바9부터 제공되는 기능이다.
    • List.of()가 더 간결하고. List.of(1,2,3)도 불변이기 때문에 사용법에 일관성이 있다. 자바9 이상을 사용한다면 이 기능을 권장한다.

 

Arrays.asList()

Arrays.asList메서드를 사용해도 다음과 같이 리스트를 생성할 수 있다.

참고로 이 메서드는 자바 1.2부터 존재했다. 자바9를 사용한다면 List.of()를 권장한다.

 

  • Arrays.asList()로 생성된 리스트는 고정된 크기를 가지지만, 요소들은 변경할 수 있다. 즉, 리스트의 길이는 변경할 수 없지만, 기존 위치에 있는 요소들을 다른 요소로 교체할 수 있다.
    • set()을 통해 요소를 변경할 수 있다.
    • add(), remove() 같은 메서드를 호출하면 예외가 발생한다. 크기를 변경할 수 없다.
      • java.lang.UnsupportedOperationExcepion발생
    • 고정도 가변도 아닌 애매한 리스트이다.

정리하면 일반적으로 List.of()를 사용하는 것을 권장한다. 다음과 같은 경우 Arrays.asList()를 선택할 수 있다.

  • 변경 가능한 요소 : 리스트 내부의 요소를 변경해야 하는 경우(단, 리스트의 크기는 변경할 수 없음)
  • 하위 호환성 : Java 9 이전 버전에서 작업해야 하는 경우

 

멀티 스레드 동기화

package collection.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SyncMain {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        
        System.out.println("list.getClass() = " + list.getClass());
        List<Integer> synchronizedList = Collections.synchronizedList(list);
        System.out.println("synchronizedList.getClass() = " + synchronizedList.getClass());
    }
}

 

실행 결과

list.getClass() = class java.util.ArrayList
synchronizedList.getClass() = class java.util.Collections$SynchronizedRandomAccessList
  • Collections.synchronizedList를 사용하면 일반 리스트를 멀티 스레드 상황에서 동기화 문제가 발생하지 않는 안전한 리스트로 만들 수 있다.
  • 동기화 작업으로 인해 일반 리스트보다 성능은 더 느리다.