자바 컬렉션 마스터하기: 효율적 자료구조 종합 가이드
자바 2 이전에는 Dictionary, Vector, Stack, Properties 같은 임시 클래스들을 제공하여 객체 그룹을 저장하고 조작했습니다. 이 클래스들이 꽤 유용했지만, 중앙의 통합된 테마가 없었습니다. 따라서 Vector 사용법이 Properties 사용법과 달랐습니다.
컬렉션 프레임워크는 여러 목표를 충족하도록 설계되었습니다.
- 프레임워크는 고성능이어야 함. 기본 컬렉션(동적 배열, 연결 리스트, 트리, 해시테이블) 구현들이 고도로 효율적이어야 함
- 서로 다른 타입의 컬렉션들이 유사한 방식으로 작동하고 높은 상호 운용성을 가져야 함
- 컬렉션을 쉽게 확장하거나 적응시킬 수 있어야 함
이를 위해 전체 컬렉션 프레임워크는 표준 인터페이스 세트를 중심으로 설계되었습니다. LinkedList, HashSet, TreeSet 등 이러한 인터페이스들의 표준 구현체들이 제공되어 바로 사용하거나, 원한다면 직접 컬렉션을 구현할 수도 있습니다.
컬렉션 프레임워크는 컬렉션을 표현하고 조작하기 위한 통합 아키텍처입니다. 모든 컬렉션 프레임워크는 다음을 포함합니다.
- 인터페이스(Interfaces) - 컬렉션을 나타내는 추상 데이터 타입. 인터페이스를 통해 컬렉션을 표현 세부사항과 독립적으로 조작 가능. 객체지향 언어에서 인터페이스들은 일반적으로 계층을 이룸
- 구현체, 즉 클래스(Implementations, i.e., Classes) - 컬렉션 인터페이스들의 구체적 구현. 본질적으로 재사용 가능한 자료구조
- 알고리즘(Algorithms) - 컬렉션 인터페이스를 구현한 객체들에 대해 검색, 정렬 등 유용한 계산을 수행하는 메서드들. 알고리즘은 다형적임: 적절한 컬렉션 인터페이스를 구현한 다양한 구현체들에 같은 메서드 사용 가능
컬렉션 외에도 프레임워크는 여러 맵 인터페이스와 클래스들을 정의합니다. 맵은 키/값 쌍을 저장합니다. 맵은 용어의 엄밀한 의미에서 컬렉션은 아니지만, 컬렉션과 완전히 통합되어 있습니다.
컬렉션 인터페이스
컬렉션 프레임워크는 여러 인터페이스를 정의합니다. 각 인터페이스 개요:
| 번호 |
인터페이스 및 설명 |
| 1 | Collection 인터페이스 - 객체 그룹을 다룰 수 있게 함. 컬렉션 계층의 최상위 |
| 2 | List 인터페이스 - Collection을 확장하며, List 인스턴스는 순서 있는 요소 컬렉션 저장 |
| 3 | Set 인터페이스 - 중복 없는 요소를 다루기 위해 Collection 확장 |
| 4 | SortedSet 인터페이스 - 정렬된 셋을 다루기 위해 Set 확장 |
| 5 | Map 인터페이스 - 고유 키를 값에 매핑 |
| 6 | Map.Entry 인터페이스 - 맵의 요소(키/값 쌍) 설명. Map의 내부 클래스 |
| 7 | SortedMap 인터페이스 - 키가 오름차순으로 유지되도록 Map 확장 |
| 8 | Enumeration 인터페이스 - 객체 컬렉션에서 요소들을 열거(한 번에 하나씩 얻기)하는 메서드 정의. Iterator에 의해 대체된 레거시 인터페이스 |
컬렉션 클래스
자바는 Collection 인터페이스들을 구현하는 표준 컬렉션 클래스들을 제공합니다. 일부 클래스는 바로 사용 가능한 완전한 구현을 제공하고, 다른 일부는 구체적 컬렉션 생성의 출발점으로 쓰이는 골격 구현을 제공하는 추상 클래스입니다.
표준 컬렉션 클래스들 요약:
| 번호 |
클래스 및 설명 |
| 1 | AbstractCollection - Collection 인터페이스 대부분 구현 |
| 2 | AbstractList - AbstractCollection 확장, List 인터페이스 대부분 구현 |
| 3 | AbstractSequentialList - 요소들의 순차적 접근을 사용하는 컬렉션용으로 AbstractList 확장 |
| 4 | LinkedList - AbstractSequentialList 확장으로 연결 리스트 구현 |
| 5 | ArrayList - AbstractList 확장으로 동적 배열 구현 |
| 6 | AbstractSet - AbstractCollection 확장, Set 인터페이스 대부분 구현 |
| 7 | HashSet - 해시 테이블용 AbstractSet 확장 |
| 8 | LinkedHashSet - 삽입 순서 반복 허용 위해 HashSet 확장 |
| 9 | TreeSet - 트리에 저장된 셋 구현. AbstractSet 확장 |
| 10 | AbstractMap - Map 인터페이스 대부분 구현 |
| 11 | HashMap - 해시 테이블용 AbstractMap 확장 |
| 12 | TreeMap - 트리용 AbstractMap 확장 |
| 13 | WeakHashMap - 약한 키를 가진 해시 테이블용 AbstractMap 확장 |
| 14 | LinkedHashMap - 삽입 순서 반복 허용 위해 HashMap 확장 |
| 15 | IdentityHashMap - AbstractMap 확장, 문서 비교 시 참조 동일성 사용 |
AbstractCollection, AbstractSet, AbstractList, AbstractSequentialList, AbstractMap 클래스들은 핵심 컬렉션 인터페이스들의 골격 구현을 제공하여 구현 노력을 최소화합니다.
이전 장에서 다룬 java.util의 레거시 클래스들:
| 번호 |
클래스 및 설명 |
| 1 | Vector - 동적 배열 구현. ArrayList와 유사하지만 차이점 존재 |
| 2 | Stack - 표준 후입선출 스택 구현하는 Vector 하위 클래스 |
| 3 | Dictionary - 키/값 저장소 나타내는 추상 클래스. Map과 유사하게 동작 |
| 4 | Hashtable - 원래 java.util의 일부로 Dictionary의 구체적 구현 |
| 5 | Properties - Hashtable 하위 클래스. 키와 값이 모두 String인 값 리스트 유지 |
| 6 | BitSet - 비트 값들을 보유하는 특수 배열 생성. 필요시 크기 증가 가능 |
컬렉션 알고리즘
컬렉션 프레임워크는 컬렉션과 맵에 적용할 수 있는 여러 알고리즘을 정의합니다. 이 알고리즘들은 Collections 클래스 내의 정적 메서드들로 정의됩니다.
여러 메서드들은 ClassCastException(비호환 타입 비교 시도 시)이나 UnsupportedOperationException(수정 불가능한 컬렉션 수정 시도 시)을 던질 수 있습니다.
Collections는 세 정적 변수 정의: EMPTY_SET, EMPTY_LIST, EMPTY_MAP. 모두 불변.
Iterator 사용법
컬렉션의 요소들을 순회하고 싶을 때가 많습니다. 예를 들어 각 요소를 표시하고 싶을 수 있습니다.
가장 쉬운 방법은 Iterator 또는 ListIterator 인터페이스를 구현한 객체인 이터레이터를 사용하는 것입니다.
Iterator는 컬렉션을 순회하며 요소를 얻거나 제거할 수 있게 합니다. ListIterator는 Iterator를 확장하여 리스트의 양방향 순회와 요소 수정을 허용합니다.
Comparator 사용법
TreeSet과 TreeMap은 요소들을 정렬된 순서로 저장합니다. 하지만 정확히 정렬된 순서가 무엇을 의미하는지는 컴퍼레이터가 정의합니다.
이 인터페이스를 통해 주어진 컬렉션을 여러 다른 방식으로 정렬할 수 있습니다. 또한 수정할 수 없는 클래스들의 인스턴스들도 정렬하는 데 사용할 수 있습니다.
요약
자바 컬렉션 프레임워크는 프로그래머에게 미리 포장된 자료구조들과 이를 조작하는 알고리즘들에 접근할 수 있게 합니다.
컬렉션은 다른 객체들에 대한 참조들을 가질 수 있는 객체입니다. 컬렉션 인터페이스들은 각 컬렉션 타입에서 수행할 수 있는 연산들을 선언합니다.
컬렉션 프레임워크의 클래스들과 인터페이스들은 java.util 패키지에 있습니다.