들어가며
자바에서 데이터를 효율적으로 저장하고 처리하려면 컬렉션(Collection) 프레임워크에 대한 이해가 필수입니다.
컬렉션은 배열의 한계를 보완하면서, 데이터를 담고 꺼내고 정렬하는 등의 작업을 더욱 유연하고 표준화된 방식으로 처리할 수 있게 해줍니다.
이 글에서는 컬렉션의 기본 개념부터 핵심 인터페이스, 주요 클래스들의 특징과 차이점까지 실용적으로 정리합니다.
1. 컬렉션 프레임워크란?
데이터를 저장하고 조작하기 위한 자료구조 클래스들의 집합
- 모든 컬렉션 클래스는 java.util 패키지에 존재
- 배열과 달리 크기 변경이 자유롭고, **자료구조별 특성(순서, 중복, 정렬 등)**을 갖춤
- 공통 인터페이스를 통해 일관된 API 제공 → 다형성 활용 가능
- List, Set, Queue 등은 인터페이스이므로 다양한 구현체(ArrayList, HashSet 등)로 교체가 가능합니다.
- 즉, 같은 메서드명 (add, remove, contains)으로 다른 자료구조의 특성에 맞는 동작을 수행할 수 있어 유연하고 확장성 있는 설계를 가능하게 합니다.
2. 주요 인터페이스 구조
java.util.Collection (인터페이스)
├─ List (인터페이스| 순서 있음, 중복 허용)
│ ├─ ArrayList
│ └─ LinkedList
├─ Set (인터페이스| 순서 없음, 중복 불가)
│ ├─ HashSet
│ └─ TreeSet
└─ Queue (인터페이스| 선입선출 구조)
└─ LinkedList (Queue 구현도 가능)
Map (인터페이스) (key-value 구조, Collection과 별도 계층)
├─ HashMap
└─ TreeMap
🔹 List, Set, Map은 **인터페이스(interface)**입니다.
🔹 ArrayList, HashSet, HashMap 등은 이 인터페이스를 **구현한 클래스(implements)**입니다. ( **상속(extends)**이 아니라 구현(implements) 관계. 예외계층에서는 상속관계였던 것이 차이가 있음)
List<String> list = new ArrayList<>();
Set<Integer> set = new HashSet<>();
Map<String, Integer> map = new HashMap<>();
- 여기서 List, Set, Map은 인터페이스 타입으로 선언된 변수
- 실제 객체는 ArrayList, HashSet, HashMap 등으로 인터페이스를 구현한 클래스 인스턴스
✅ 그럼 추상 클래스는 없나요?
있습니다! 일부 구현체는 인터페이스 + 추상 클래스 + 구체 클래스 구조를 가집니다.
List (interface)
↑
AbstractList (추상 클래스)
↑
ArrayList (구현 클래스)
- AbstractList, AbstractSet, AbstractMap → 중복 구현을 줄이기 위한 추상 클래스
- ArrayList나 HashMap은 이걸 상속(extends) 받으며, 동시에 인터페이스를 implements합니다
- Collection은 단일 요소 집합(List, Set, Queue)이고,
- Map은 키와 값의 쌍을 다루는 완전히 다른 구조의 자료형이기 때문에 별도로 설계되었습니다.
- 즉, Map은 “요소”가 아닌 “매핑 관계”를 다루므로, add() 대신 put()을 사용하고, 순회 방식도 다릅니다.
✔️ "매핑 관계"란?
Key를 기준으로 고유하게 대응되는 Value를 가지는 구조를 의미합니다. 예: 주민등록번호(키) → 이름(값)
항목 | 구현 기반 (Collection) | 상속 기반 (Exception) |
설계 목적 | 다양한 자료구조를 유연하게 교체 가능 | 특정 종류의 예외를 구분하고, 계층적으로 처리 |
확장 방식 | implements로 기능을 구현 | extends로 의미 계층 정의 |
이유 | 동작 방식은 클래스마다 다름 (ex. ArrayList vs LinkedList) | 의미 구조는 고정되어야 함 (ex. RuntimeException은 예외다) |
✔️ "의미 구조 고정"이란?
NullPointerException, IOException 등 예외 클래스 이름만 보고 어떤 오류인지 바로 이해할 수 있도록 계층적 이름과 관계를 유지하는 설계입니다.
의미적으로도 일관된 구조를 유지하는 것이 중요하기 때문에, 예외는 상속 기반으로 표현합니다.
→ 즉, 컬렉션은 행동 다형성, 예외는 의미 분류 중심 설계입니다.
자바 컬렉션은 자료구조와 객체지향의 만남입니다.
기초 개념을 정확히 잡고, 각 자료구조의 특성을 이해하면 효율적인 데이터 처리가 가능합니다.
3. List – 순서를 보장하고 중복을 허용
✅ 특징
- 인덱스로 접근 가능
- 순서를 유지
- 중복 데이터 허용
중복 허용과 순서 유지의 조합은 데이터의 삽입 순서나 위치가 중요할 때 필수적입니다.
예: 장바구니 목록, 순위표, 최근 본 항목 등
✅ 대표 구현체
클래스 | 특징 |
ArrayList | 배열 기반, 탐색 빠름, 삽입/삭제 느림 |
LinkedList | 노드 기반, 삽입/삭제 빠름, 탐색 느림 |
✅ 예시
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("A"); // 중복 허용
new ArrayList<>()에서 꺾쇠 괄호 안을 생략한 이유는, 앞에서 이미 제네릭 타입을 List<String>으로 지정했기 때문에 컴파일러가 타입 추론을 할 수 있기 때문입니다.
이를 Java 7부터 도입된 다이아몬드 연산자(<>) 문법이라고 부릅니다.
4. Set – 중복을 허용하지 않는 집합
✅ 특징
- 순서를 보장하지 않음 (단, TreeSet은 정렬됨)
- 중복 불가
Set은 중복 제거와 **집합 연산(합집합, 교집합 등)**이 필요한 경우 유용합니다.
예: 유저 고유 ID 저장, 태그 목록, 중복 없는 이벤트 로그 수집 등
✅ 대표 구현체
클래스 | 특징 |
HashSet | 해시 기반, 빠른 검색, 순서 없음 |
TreeSet | 이진트리 기반, 자동 정렬, 성능 다소 느림 |
✅ 예시
Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("A"); // 중복 무시됨
5. Map – 키와 값의 쌍으로 구성된 구조
Collection 인터페이스는 아니지만, 컬렉션처럼 함께 다루는 자료구조
✅ 특징
- Key → Value 매핑 구조
- Key는 중복 불가, Value는 중복 허용
Map은 JS의 Object, Python의 dict와 매우 유사한 구조입니다.
✅ 대표 구현체
클래스 | 특징 |
HashMap | 순서 없음, null 허용 |
TreeMap | Key 기준 정렬, 성능 느림 |
✅ 예시
Map<String, Integer> map = new HashMap<>();
map.put("apple", 3);
map.put("banana", 5);
map.put("apple", 10); // key 중복 → 덮어쓰기
6. Queue – 순서대로 처리하는 선입선출 구조
✅ 특징
- FIFO(First-In-First-Out)
- LinkedList, ArrayDeque 등으로 구현 가능
Queue는 작업 예약, 요청 처리, 비동기 이벤트 처리 등에서 자주 사용됩니다.예: 프린터 대기열, 메시지 큐, 게임 이벤트 처리 등
✅ 예시
Queue<String> queue = new LinkedList<>();
queue.add("A");
queue.add("B");
System.out.println(queue.poll()); // A
System.out.println(queue.poll()); // B
7. 컬렉션 사용 시 유의점
- ✅ **제네릭(Generic)**을 사용하여 타입 안정성 확보
List<String> names = new ArrayList<>();
→ List 인터페이스나 클래스 선언 시 타입을 지정함으로써 런타임 오류를 줄이고 컴파일러가 타입을 체크하도록 도와줌
- ✅ null 처리 주의
- 일부 컬렉션 구현체는 null 허용 (ArrayList, HashMap)
- TreeMap, TreeSet 등은 null 사용 시 NullPointerException 발생 가능 → 문서 확인 필수
- ✅ 동기화 필요 시
- 기본 컬렉션은 스레드 안전하지 않음
- 멀티스레드 환경에서 공유할 경우 Collections.synchronizedList() 등으로 감싸야 함
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
마치며 – 다음 글 예고
📂 language / java 카테고리에서는 다음 내용을 이어서 다룹니다:
- Iterator, for-each, Stream을 활용한 컬렉션 순회 방식 비교
- Set과 Map의 해시 기반 내부 구조 분석
- 성능 비교: ArrayList vs LinkedList, HashMap vs TreeMap
자바 컬렉션은 자료구조와 객체지향의 만남입니다.
기초 개념을 정확히 잡고, 각 자료구조의 특성을 이해하면 효율적인 데이터 처리가 가능합니다.
📌 이전 글 다시보기
👉 자바의 예외 처리 흐름과 커스텀 예외 만들기 – 안정적인 코드 작성의 시작
📌 다음 글 미리보기
👉 최신 문법 (var, record, Stream API 등)
📚 Java 시리즈 전체 보기
'language > java' 카테고리의 다른 글
언어 자바 - 심화 학습 리스트업 (0) | 2025.04.20 |
---|---|
자바 최신 문법 정리 – var, record, Stream API로 더 간결하게 (1) | 2025.04.16 |
자바의 예외 처리 흐름과 커스텀 예외 만들기 – 안정적인 코드 작성의 시작 (0) | 2025.04.14 |
자바의 상속, 다형성, 인터페이스 제대로 이해하기 – 객체지향의 핵심 기둥 (1) | 2025.04.13 |
자바의 클래스와 객체 개념 정복하기 – 객체지향의 출발점 (1) | 2025.04.13 |
댓글