Collection 핵심정리
1. Collection의 정의와 자바의 특징
Collection의 정의
컴퓨터 공학에서 컬렉션(Collection)은 다수의 데이터(객체)를 그룹화하여 효율적으로 관리하기 위한 '자료구조(Data Structure)' 또는 '컨테이너(Container)'를 의미하는 범용적인 용어입니다.
Java 언어의 특화 개념인가?
- 개념 자체는 모든 언어의 공통 사항입니다. C++, 파이썬, 자바스크립트 등 대부분의 프로그래밍 언어에 동일한 개념이 존재합니다.
- 다만, 자바는 표준 라이브러리 차원에서 인터페이스와 클래스를 정형화하여 '자바 컬렉션 프레임워크(Java Collection Framework)'라는 고유의 체계로 제공하여 쉽게 사용이 가능합니다.
자바 컬렉션의 핵심 구조
자바 컬렉션은 java.util 패키지에 속하며, 크게 세 가지 주요 인터페이스를 중심으로 상속 구조가 이루어져 있습니다.
- List: 순서가 있으며, 데이터의 중복을 허용합니다. (예: ArrayList, LinkedList)
- Set: 순서가 없으며, 데이터의 중복을 허용하지 않습니다. (예: HashSet, TreeSet)
- Queue: 먼저 들어온 데이터가 먼저 나가는 FIFO(First-In-First-Out) 구조를 가집니다. (예: PriorityQueue, ArrayDeque)
- (참고) Map은 구조상 Collection 인터페이스를 직접 상속받지 않지만, 구조적 연관성 때문에 컬렉션 프레임워크의 일부라 할 수 있습니다.
2. Collection 사용의 장점과 적합한 상황
컬렉션을 사용하면 좋은 점
- 동적 크기 할당 고정 크기인 배열과 달리, 메모리가 허용하는 한 데이터의 개수에 따라 크기가 자동으로 늘어나고 줄어듭니다.
- 표준화된 고성능 알고리즘 정렬, 검색, 데이터 순회 등 검증되고 최적화된 자료구조 알고리즘을 기본 제공하므로 개발 생산성이 높아집니다.
- 다형성을 통한 유지보수성 향상 인터페이스 기반으로 설계되어 있어, 요구사항 변경 시 구현체(예: ArrayList -> LinkedList)를 쉽게 교체할 수 있습니다.
어느 상황에서 쓰면 좋은가?
- 저장해야 할 데이터의 개수를 미리 예측할 수 없을 때
- 데이터의 중복을 자동으로 제거하고 유일한 값만 관리해야 할 때 (Set 활용)
- 키-값(Key-Value) 쌍으로 묶어 특정 데이터에 빠르게 접근해야 할 때 (Map 활용)
- 작업 스케줄링이나 메시지 대기열처럼 순차적인 처리가 필요할 때 (Queue 활용)
3. Collection 직접 구현 가능 여부
네, 직접 구현할 수 있습니다. 두 가지 접근 방식이 있습니다.
- 표준 인터페이스 구현
java.util.Collection또는List,Set같은 하위 인터페이스를 상속받아(implements) 자바 표준 규격에 맞는 커스텀 컬렉션 클래스를 만들 수 있습니다. - 독립적 구조 구현 자바 프레임워크 체계와 상관없이, 배열(Array)이나 노드(Node) 포인터 구조를 활용해 나만의 독창적인 데이터 컨테이너를 직접 코딩할 수 있습니다. 실무에서는 표준 인터페이스를 직접 처음부터 구현하기보다는, 기존 컬렉션을 상속 받아 내부 비즈니스 유효성 검증 로직을 추가하는 방식을 주로 사용합니다.
4. Collection 사용 시 주의해야 할 점
멀티스레드 환경의 안정성 문제
기본적인 컬렉션(ArrayList, HashMap 등)은 동기화 처리가 되어 있지 않습니다. 멀티스레드 환경에서 여러 스레드가 동시에 데이터를 수정하면 ConcurrentModificationException이 발생하거나 데이터가 유실될 수 있습니다. 멀티스레드 환경에서는 ConcurrentHashMap이나 CopyOnWriteArrayList 같은 동기화 컬렉션을 사용해야 합니다.
성능 및 메모리 오버헤드
- 시간 복잡도 자원의 삽입, 삭제, 조회가 빈번한 형태에 따라 적절한 자료구조를 선택해야 합니다. 대량의 중간 삽입/삭제가 일어나는 환경에서 ArrayList를 사용하면 심각한 성능 저하가 발생합니다.
- 기본 타입 제약 자바 컬렉션은 기본 타입(int, char 등)을 담지 못하고 객체(Wrapper 클래스: Integer, Character 등)만 저장할 수 있습니다. 이로 인해 자동 박싱/언박싱(Auto-boxing/Unboxing)이 일어나며 대용량 처리 시 메모리 오버헤드가 발생합니다.
5. 핵심 주의사항: 참조 변수 공유로 인한 데이터 오염
자바 컬렉션은 객체의 실제 값이 아닌 객체의 메모리 주소(참조값)를 저장합니다. 이 특성을 정확히 이해하지 못하면 원본 데이터가 의도치 않게 조작되는 '데이터 오염(Side Effect)' 버그가 발생합니다.
데이터 오염의 대표적인 시나리오
얕은 복사(Shallow Copy)로 인한 오염
새로운 리스트 객체를 생성하여 기존 리스트를 복사하더라도, 내부에 담긴 개별 객체들의 주소는 공유됩니다.
java
class User{
String name;
User(String name) { this.name = name; }
}
List<User> originalList = new ArrayList<>();
originalList.add(new User("홍길동"));
// 얕은 복사 실행 (새로운 리스트를 만들었으나 내부 원소 주소는 동일)
List<User> copiedList = new ArrayList<>(originalList);
// 복사본의 객체를 수정
copiedList.get(0).name = "이순신";
// 원본 데이터 확인 결과 -> 원본도 "이순신"으로 오염됨
System.out.println(originalList.get(0).name);getter 메서드를 통한 캡슐화 파괴
클래스 내부의 컬렉션 참조 주소를 외부 getter로 그대로 반환하면, 외부에서 private 멤버 변수를 마음대로 조작할 수 있게 됩니다.
java
class Team{
private List<String> members = new ArrayList<>();
// 내부 컬렉션 주소를 그대로 노출
public List<String> getMembers(){
return this.members;
}
}데이터 오염 해결 방안
- 방어적 복사(Defensive Copy)
생성자나 getter 반환 시 원본의 주소를 주지 않고
new ArrayList<>(원본)형태로 새 인스턴스에 담아 반환합니다. - 불변 컬렉션(Unmodifiable Collection)
Java 9 이상에서 제공하는
List.copyOf()등을 활용하여 읽기 전용 컬렉션으로 반환합니다. 외부에서 수정을 시도할 경우UnsupportedOperationException이 발생하여 안전합니다. - 깊은 복사(Deep Copy)
리스트뿐만 아니라 리스트 내부에 든 객체들까지 모두
new키워드로 새롭게 인스턴스를 생성하여 완전히 연결고리를 끊어냅니다.
6. 타 프로그래밍 언어와의 비교
자바 컬렉션 프레임워크가 가지는 타 언어 대비 차별점과 특화점은 다음과 같습니다.
댓글
GitHub 계정으로 의견이나 질문을 남길 수 있습니다.