컬렉션 프레임워크 (Collection Framework)
- 여러 가지 자료 구조(Data Structure)를 쉽게 사용할 수 있도록 자바에서 미리 구현하여 제공하는 클래스를 말한다.
- 대표적인 인터페이스로는 List 인터페이스, Set 인터페이스, Map 인터페이스 등이 있다.
Collection 계열 클래스
![[Collection 계열 클래스의 계층 구조]](http://t1.daumcdn.net/tistory_admin/static/images/xBoxReplace_250.png)
Collection 인터페이스에 선언되어 있는 주요 메소드들
- 모든 컬렉션 인터페이스에 공통적으로 존재하는 메소드이다.
- Collection 인터페이스를 상속하는 클래스들은 추상 메소드를 활용하여 다양한 방식으로 데이터를 관리할 수 있다.
추상 메소드 | 설명 |
int size() | 현재 컬렉션에 포함된 요소의 개수를 반환한다. |
boolean isEmpty() | 현재 컬렉션이 비어 있는지 여부를 반환한다. |
boolean contains(Object o) | 현재 컬렉션에 지정된 요소가 포함되어 있는 지 여부를 반환한다. |
boolean add(E e) | 지정된 요소를 현재 컬렉션에 추가한다. |
boolean remove(Object o) | 지정된 요소를 현재 컬렉션에서 제거한다. |
boolean addAll(Collection<? extends E> c) | 지정된 컬렉션의 모든 요소를 현재 컬렉션에 추가한다. |
void clear() | 현재 컬렉션의 모든 요소를 제거한다. |
boolean removeAll(Collection<?> c) | 현재 컬렉션에서 지정된 컬렉션에 포함된 모든 요소를 제거한다. |
boolean retainAll(Collection<?> c) | 현재 컬렉션에서 지정된 컬렉션에 포함된 요소만 남기고 다른 모든 요소를 제거한다. |
Iterator<E> iterator() | 현재 컬렉션을 순회할 때 사용할 수 있는 Iterator 객체를 반환한다. |
Object[] toArray() | 현재 컬렉션에 포함된 모든 요소를 배열로 반환한다. |
<T> T[] toArray(T[] a) | 현재 컬렉션에 포함된 모든 요소를 지정된 배열에 저장하여 반환한다. |
List 인터페이스
- 배열과 비슷하게 동작하며, 데이터 저장 시 순서(Index)가 부여된다.
- 배열과의 가장 큰 차이점은 데이터 추가 시 자동으로 저장공간이 늘어난다.
- 데이터의 중복이 허용될 수 잇으며, 요소의 삽입 순서를 유지한다.
- List 인터페이스의 추상 메소드
추상 메소드 | 설명 |
void add(int index, E element) | 지정된 인덱스에 요소를 추가한다. |
boolean addAll(int index, Collection<? extends E> c) | 지정된 인덱스에 컬렉션의 모든 요소를 추가한다. |
E remove(int index) | 지정된 인덱스의 요소를 삭제하고 그 요소를 반환한다. |
E get(int index) | 지정된 인덱스의 요소를 반환한다. |
E set(int index, E element) | 지정된 인덱스의 요소를 새 요소로 대체하고 이전 요소를 반환한다. |
int indexOf(Object o) | 지정된 요소의 첫 번째 인덱스를 반환합니다. 해당 요소가 없으면 -1을 반환한다. |
int lastIndexOf(Object o) | 지정된 요소의 마지막 인덱스를 반환 한다. |
List<E> subList(int fromIndex, int toIndex) | 지정된 범위의 요소로 구성된 부분 리스트를 반환한다. (fromIndex는 포함하고, toIndex는 포함하지 않음) |
void sort(Comparator<? super E> c) | 지정된 Comparator에 따라 List를 정렬한다. Comparator를 제공하지 않으면 요소의 자연 순서에 따라 정렬한다. |
Iterator<E> iterator() | 현재 컬렉션을 순회할 때 사용할 수 있는 Iterator 객체를 반환한다. |
Object[] toArray() | 현재 컬렉션에 포함된 모든 요소를 배열로 반환한다. |
<T> T[] toArray(T[] a) | 현재 컬렉션에 포함된 모든 요소를 지정된 배열에 저장하여 반환한다. |
ArrayList 클래스
- List 계열의 클래스 중 가장 많이 사용되는 클래스이다.
- 객체 저장 시 Index가 순서대로 지정된다.
- 저장하는 객체의 개수에 제한이 없다.
- 동기화를 지원하지 않으며, 멀티스레드 환경에서 안정성을 보장할 수 없다.
- ArrayList 클래스를 사용한 List 인터페이스의 기능 구현 예시
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
// ArrayList 생성
List<String> list = new ArrayList<>();
// 요소 추가
list.add("Apple");
list.add("Banana");
list.add("Orange");
// 요소 접근과 출력
System.out.println("List: " + list);
// 특정 위치의 요소 가져오기
String fruit = list.get(0);
System.out.println("First fruit: " + fruit);
// 요소 삭제
list.remove("Orange");
// 변경된 리스트 출력
System.out.println("Modified List: " + list);
// 리스트의 크기 출력
System.out.println("Size of List: " + list.size());
}
}
Vector 클래스
- 내부 메소드들이 동기화 되어 있으며, 이로 인해 멀티 스레드 환경에서 여러 스레드가 동시에 Vector 객체를 수정할 때 데이터의 일관성을 유지하는 데 도움이 된다.
- 동기화된 메소드 호출로 인하여 ArrayList 보다 성능이 떨어질 수 있다. 따라서, 단일 스레드 환경에서는 ArrayList를 사용하는 것이 성능상의 이점이 있을 수 있다.
- Vector 클래스 기능 구현 예시
import java.util.Vector;
public class Main {
public static void main(String[] args) {
// Vector 생성
Vector<String> vector = new Vector<>();
// 요소 추가
vector.add("Apple");
vector.add("Banana");
vector.add("Orange");
// 요소 접근과 출력
System.out.println("Vector: " + vector);
// Vector의 크기 출력
System.out.println("Size of Vector: " + vector.size());
}
}
LinkedList 클래스
- 이중 연결 리스트(doubly linked list) 기반의 구현체이다.
- 이중 연결 리스트는 각 노드가 이전 노드와 다음 노드의 참조를 가지고 있는 구조로, 요소들을 순차적으로 연결하여 저장한다.
- 요소의 추가나 삭제가 매우 빠르며, 특히 리스트의 시작이나 끝에 요소를 추가하거나 삭제할 때 ArrayList보다 유리할 수 있다.
- 인덱스로 요소를 찾는 경우 시작부터 해당 인덱스까지 순차적으로 접근해야 하므로 시간 복잡도는 O(n)으로 인덱스를 통한 요소 접근이 느리다.
- 데이터의 추가 삭제가 빈번한 경우 LinkedList를 사용하고, 검색 작업이 빈번한 경우 ArrayList를 사용하면 좋다.
- 주요 메소드
주요 메소드 | 설명 |
void addFirst(E e) | 리스트의 시작 부분에 요소를 추가한다. |
void addLast(E e) | 리스트의 끝 부분에 요소를 추가한다. |
E getFirst() | 리스트의 첫 번째 요소를 반환한다. |
E getLast() | 리스트의 마지막 요소를 반환한다. |
E removeFirst() | 리스트의 첫 번째 요소를 삭제하고 반환한다. |
E removeLast() | 리스트의 마지막 요소를 삭제하고 반환한다. |
boolean offer(E e) | 리스트의 끝에 요소를 추가한다. |
E poll() | 리스트의 첫 번째 요소를 삭제하고 반환하며, 리스트가 비어 있으면 null을 반환한다. |
E peek() | 리스트의 첫 번째 요소를 반환하며, 리스트가 비어 있으면 null을 반환한다. |
- LinkedList 클래스 기능 구현 예시
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
// LinkedList 생성
LinkedList<String> linkedList = new LinkedList<>();
// 요소 추가
linkedList.add("Apple");
linkedList.add("Banana");
linkedList.add("Orange");
// 특정 위치의 요소 가져오기
String fruit = linkedList.get(0);
System.out.println("First fruit: " + fruit);
// LinkedList의 크기 출력
System.out.println("Size of LinkedList: " + linkedList.size());
}
}
Queue 인터페이스
- FIFO(First-In-First-Out) 방식의 데이터 구조를 구현하기 위한 인터페이스이다.
- 요소가 입력된 순서대로 저장되고, 요소는 처음에 입력된 것부터 순서대로 제거된다.
- 실제 큐의 기능은 java.util.Queue 인터페이스를 구현한 LinkedList 클래스 또는 PriorityQueue 클래스를 이용한다.
- LinkedList 클래스를 사용한 Queue 인터페이스의 기능 구현 예시
import java.util.LinkedList;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
// Queue 인터페이스를 구현한 LinkedList 생성
Queue<String> queue = new LinkedList<>();
// 요소 추가
queue.add("Apple");
queue.add("Banana");
queue.add("Orange");
// 요소 제거
String removed = queue.poll();
System.out.println("Removed element: " + removed);
// 큐의 크기 확인
System.out.println("Queue size: " + queue.size());
// 모든 요소 제거
queue.clear();
System.out.println("Queue cleared. Is empty? " + queue.isEmpty());
}
}
Set 인터페이스
- 동일한 요소가 중복되어 추가될 수 없으며, 이미 집합에 존재하는 요소들과 equality를 통해 중복 여부를 판단한다.
- 요소가 추가된 순서나 다른 기준에 따라 요소들이 정렬되지 않는다.
- 각 요소는 고유한 값을 가지므로, 동일한 객체를 다시 추가하려고 해도 추가되지 않는다.
- 대표적인 클래스로는 HashSet, TreeSet, LinkedHashSet 등이 있다.
- HashSet의 경우, 해시 테이블을 사용하여 요소를 저장하므로 검색 및 추가 연산이 평균적으로 빠르다.
- HashSet 클래스를 사용한 Set 인터페이스의 기능 구현 예시
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
// HashSet 생성
Set<String> set = new HashSet<>();
// 요소 추가
set.add("Apple");
set.add("Banana");
set.add("Orange");
// 중복된 요소 추가 시도
boolean added = set.add("Apple");
System.out.println("Added 'Apple' again: " + added); // false 반환
// 요소 포함 여부 확인
boolean containsBanana = set.contains("Banana");
System.out.println("Set contains 'Banana': " + containsBanana); // true 반환
// 요소 삭제
set.remove("Orange");
// Set의 크기 확인
System.out.println("Set size: " + set.size()); // 2 반환
// 모든 요소 출력
System.out.println("All elements in set: " + set); // 순서 없이 출력된다.
}
}
⊙ 참고 문헌
- 이병승, 「초보 개발자를 위한 자바:한 권으로 배우는 자바 마스터 가이드 북」, 영진닷컴, 2024, p701 - 729
- 마종현, 「제로베이스 백엔드 취업 파트타임 스쿨 5기:Part 01. Java 기초-Chapter 01. Java 프로그래밍-컬렉션 프레임워크」, 제로베이스, 2024, https://zero-base.co.kr/
- Java™ Platform, Standard Edition 8 API Specification, 2024.07.23, https://docs.oracle.com/javase/8/docs/api/java/util/package-summary.html