- Collection: 가장 상위 인터페이스
- Set: 중복을 허용하지 않는 집합을 처리하기 위한 인터페이스
- SortedSet: 오름차순을 갖는 Set 인터페이스
- List: 순서가 있는 집합을 처리하기 위한 인터페이스이기 때문에 인덱스가 있어 위치를 지정하여 값을 찾을 수 있다.
- Queue: 여러 개의 객체를 처리하기 전에 담아서 처리할 때 사용하기 위한 인터페이스이다. 기본적으로 FIFO를 따른다.
- Map: 키와 값의 쌍으로 구성된 객체의 집합을 처리하기 위한 인터페이스. 중복되는 키를 허용하지 않는다.
- SortedMap: 키를 오름차순으로 정렬하는 Map 인터페이스
Set 인터페이스를 구현한 클래스로는 HashSet, TreeSet, LinkedHashSet 세 가지가 있다.
- HashSet: 데이터를 해쉬 테이블에 담는 클래스로 순서 없이 저장된다.
- TreeSet: red-black이라는 트리에 데이터를 담는다. 값에 따라서 순서가 정해진다. 데이터를 담으면서 동시에 정렬하기 때문에 HashSet보다 성능상 느리다.
- LinkedHashSet: 해쉬 테이블에 데이터를 담는데, 저장된 순서에 따라서 순서가 결정된다.
List 인터페이스를 구현한 클래스들은 담을 수 있는 크기가 자동으로 증가되므로, 데이터의 개수를 확실히 모를 때 유용하게 사용된다.
- Vector: 객체 생성 시에 크기를 지정할 필요가 없는 배열 클래스이다.
- ArrayList: Vector와 비슷하지만, 동기화 처리가 되어 있지 않다.
- LinkedList: ArrayList와 동일하지만, Queue 인터페이스를 구현했기 때문에 FIFO 큐 작업을 수행한다.
List의 가장 큰 단점은 데이터가 많은 경우 처리 시간이 늘어난다 는 점이다. 가장 앞에 있는 데이터를 지우고 그 다음 1번 데이터부터 마지막 데이터까지 한 칸씩 옮기는 작업을 수행하야 하므로, 데이터가 적을 때는 상관없지만, 데이터가 많으면 많을수록 가장 앞에 있는 데이터를 지우는데 소요되는 시간이 증가한다.
Queue 인터페이스를 구현한 클래스는 두 가지로 나뉜다. java.util 패키지에 속하는 LinkedList와 PriorityQueue는 일반적인 목적의 큐 클래스이며, java.util.concurrent 패키지에 속하는 클래스들은 ConcurrentQueue 클래스이다.
- PriorityQueue: 큐에 추가된 순서와 상관없이 먼저 생성된 객체가 먼저 나오도록 되어 있는 Queue
- LinkedBlockingQueue: 저장할 데이터의 크기를 선택적으로 정할 수도 있는 FIFO 기반의 링크 노드를 사용하는 블로킹 Queue
- ArrayBlockingQueue: 저장되는 데이터의 크기가 정해져 있는 FIFO 기반의 블로킹 Queue
- PriorityBlockingQueue: 저장되는 데이터의 크기가 정해져 있지 않고, 객체의 생성순서에 따라서 순서가 저장되는 블로킹 Queue
- DelayQueue: 큐가 대기하는 시간을 지정하여 처리하도록 되어 있는 Queue
- SynchronousQueue: put() 함수를 호출하면, 다른 스레드에서 take() 함수가 호출될 때까지 대기하도록 되어 있는 Queue. 이 큐에는 저장되는 데이터가 없다. API에서 제공하는 대부분의 함수는 0이나 null을 리턴한다.
Blocking Queue란 크기가 지정되어 있는 큐에 더 이상 공간이 없을 때, 공간이 생길 때까지 대기하도록 만들어진 큐를 의미한다.
Map은 Key와 Value 쌍으로 저장되는 구조체이다. 그래서, 단일 객체만 저장되는 다른 Collection API들과는 다르게 따로 구분되어 있다.
- HashTable: 데이터를 해쉬 테이블에 담는 클래스이다. 내부에서 관리하는 해쉬 테이블 객체가 동기화되어 있다.
- HashMap: 데이터를 해쉬 테이블에 담는 클래스이다. HashTable 클래스와는 다르게 null 값을 허용한다는 것과 동기화되어 있지 않다.
- TreeMap: red-black 트리에 데이터를 담는다. TreeSet과는 다르게 키에 의해 순서가 정해진다.
- LinkedHashMap: HashMap과 거의 동일하며 이중 연결 리스트(Doubly-LinkedList)라는 방식을 사용하여 데이터를 담는다는 점만 다르다.
List 관련 클래스 중 무엇이 빠를까?
대상 | 평균 응답 시간(마이크로초) |
---|---|
ArrayList | 4 |
Vector | 105 |
LinkedList | 1,512 |
LinkedListPeek | 0.16 |
- LinkedList는 Queue 인터페이스를 상속받기 때문에, get()보다는 순차적으로 결과를 받아오는 peek()이나 poll() 함수를 사용해야 한다.
- Vector는 여러 스레드에서 접근할 경우를 방지하기 위해 get() 함수에 synchronized가 선언되어 있어서 성능 저하가 발생할 수 밖에 없다.
Map 관련 클래스 중 무엇이 빠를까?
대부분의 클래스들이 동일하지만, 트리 형태로 처리하는 TreeMap 클래스가 가장 느리다.
Collection 관련 클래스의 동기화
HashSet, TreeSet, LinkedHashSet, ArrayList, LinkedList, HashMap, TreeMap, LinkedHashMap은 동기화(synchronized)되지 않은 클래스이다. 이와는 반대로 동기화되어 있는 클래스로는 Vector와 HashTable이 있다.
Map의 경우 키 값들을 Set으로 가져와 Iterator를 통해 데이터를 처리하는 경우가 발생한다. 이때 ConcurrentModificationException이라는 예외가 발생할 수 있다. 이 예외가 발생하는 여러 가지 원인 중 하나는 스레드에서 Iterator로 어떤 Map 객체의 데이터를 꺼내고 있는데, 다른 스레드에서 해당 Map을 수정하는 경우다.