컬렉션 프레임워크 개요 — Java Collections의 전체 구조

Iterable→Collection→List/Set/Queue 계층, Map의 별도 계층, 주요 구현체 선택 기준 표, Iterable·Collection 공통 인터페이스 메서드, 그리고 어떤 컬렉션을 언제 써야 하는지 가이드

· 5 min read · PALDYN Team

지난 글에서 제네릭 사용 시 주의해야 할 함정들을 정리했다. 이번에는 **Java 컬렉션 프레임워크(Collection Framework)**를 개관한다. 컬렉션 프레임워크는 데이터를 저장·검색·수정·순회하는 데이터 구조와 알고리즘의 통합 체계다. Java 2(1.2)에서 도입되어 이후 버전마다 꾸준히 확장되었다.

전체 계층 구조

Iterable<E>
  └─ Collection<E>
       ├─ List<E>         — 순서 있는 시퀀스, 중복 허용
       │    ├─ ArrayList
       │    ├─ LinkedList
       │    └─ Vector (레거시)
       ├─ Set<E>          — 중복 없는 집합
       │    ├─ HashSet
       │    ├─ LinkedHashSet
       │    └─ SortedSet → TreeSet
       └─ Queue<E>        — FIFO / 우선순위
            ├─ ArrayDeque  (Deque 구현)
            └─ PriorityQueue

Map<K,V>  (Collection 계층에 속하지 않음)
  ├─ HashMap
  ├─ LinkedHashMap
  ├─ TreeMap
  └─ ConcurrentHashMap

Map은 키-값 쌍을 다루기 때문에 Collection 계층에 속하지 않는다. 하지만 같은 패키지 java.util에 있으며, 실무에서 가장 많이 쓰이는 자료구조 중 하나다.

컬렉션 프레임워크 계층 구조

Iterable<E> — 반복 가능의 근원

Iterablefor-each 루프를 가능하게 하는 인터페이스다. iterator() 메서드 하나만 있다.

public interface Iterable<T> {
    Iterator<T> iterator();

    // Java 8+
    default void forEach(Consumer<? super T> action) { ... }
    default Spliterator<T> spliterator() { ... }
}

IteratorhasNext(), next(), remove() 세 메서드를 제공한다.

List<String> list = List.of("a", "b", "c");

// for-each (내부적으로 iterator 사용)
for (String s : list) System.out.println(s);

// 명시적 iterator
Iterator<String> it = list.iterator();
while (it.hasNext()) System.out.println(it.next());

Collection<E> — 컬렉션의 공통 인터페이스

Collection은 모든 단일 원소 컬렉션이 구현하는 인터페이스다. 핵심 메서드:

// 원소 수
int size();
boolean isEmpty();

// 포함 여부
boolean contains(Object o);
boolean containsAll(Collection<?> c);

// 추가
boolean add(E e);
boolean addAll(Collection<? extends E> c);

// 제거
boolean remove(Object o);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
void clear();

// 변환
Object[] toArray();
<T> T[] toArray(T[] a);

// Java 8+
Stream<E> stream();
Stream<E> parallelStream();

구현체 선택 가이드

컬렉션 구현체 선택 가이드

List 선택

  • ArrayList: 인덱스 접근이 많고, 끝에서만 추가/삭제 → 기본 선택
  • LinkedList: 양 끝 삽입/삭제가 빈번하거나 Deque가 필요 → 그 외엔 ArrayList가 더 빠름

Set 선택

  • HashSet: 순서 불필요, 빠른 contains → 기본 선택
  • LinkedHashSet: 삽입 순서를 유지하면서 중복 제거
  • TreeSet: 정렬된 순서가 필요, headSet/tailSet 범위 검색

Map 선택

  • HashMap: 빠른 조회/삽입, 순서 불필요 → 기본 선택
  • LinkedHashMap: 삽입·접근 순서 유지, LRU 캐시 구현에 활용
  • TreeMap: 키 정렬 순서, 범위 검색(subMap, headMap, tailMap)
  • ConcurrentHashMap: 멀티스레드 환경에서 안전한 동시 접근

Null 허용 여부

컬렉션마다 null 허용 정책이 다르다.

구현체null 원소/키null 값
ArrayListO
HashSetO (1개)
LinkedHashSetO (1개)
TreeSetX (NullPointerException)
HashMapO (키 1개)O
TreeMapX (키)O
ConcurrentHashMapXX

TreeSetTreeMap은 자연 정렬이나 Comparator를 사용하는데, null과의 비교가 불가능해서 예외를 던진다.

Collections 유틸리티 클래스

java.util.Collections에 있는 정적 메서드들은 컬렉션 조작에 자주 쓰인다.

List<Integer> list = new ArrayList<>(List.of(3, 1, 4, 1, 5));

Collections.sort(list);                   // [1, 1, 3, 4, 5]
Collections.reverse(list);               // [5, 4, 3, 1, 1]
Collections.shuffle(list);               // 무작위 섞기
Collections.min(list);                   // 1
Collections.max(list);                   // 5
Collections.frequency(list, 1);          // 2

// 불변 래퍼
List<Integer> immutable = Collections.unmodifiableList(list);
// immutable.add(6); // UnsupportedOperationException

지난 글: 제네릭 함정 — 흔한 실수와 주의사항

다음 글: List와 ArrayList — 순서 있는 컬렉션의 핵심


읽어주셔서 감사합니다. 😊