Set 계열 컬렉션 특성
Set 인터페이스는 Collection 계층구조에서 유일성과 순서 제어를 제공합니다. 주요 구현체별 특징:
public class SetExample {
public static void main(String[] args) {
// HashSet: 순서 없음, 중복 불가
// Set<String> items = new HashSet<>();
// LinkedHashSet: 삽입 순서 유지
// Set<String> items = new LinkedHashSet<>();
// TreeSet: 자동 정렬
Set<String> items = new TreeSet<>();
items.add("DataA");
items.add("DataC");
items.add("DataC"); // 중복 시도
items.add("DataB");
System.out.println(items); // [DataA, DataB, DataC]
}
}
HashSet의 해시 기반 동작 원리
HashSet은 해시 테이블로 구현되며 객체의 해시값을 기반으로 저장 위치를 결정합니다.
class Employee {
private String id;
private int experience;
public Employee(String id, int exp) {
this.id = id;
this.experience = exp;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Employee emp = (Employee) obj;
return experience == emp.experience && id.equals(emp.id);
}
@Override
public int hashCode() {
return 31 * id.hashCode() + experience;
}
}
public class HashAnalysis {
public static void main(String[] args) {
Employee emp1 = new Employee("E1001", 3);
Employee emp2 = new Employee("E1002", 3);
System.out.println(emp1.hashCode());
System.out.println(emp2.hashCode());
}
}
해시 테이블 구조
- JDK 8 이전: 배열 + 연결 리스트
- JDK 8 이후: 배열 + 연결 리스트 + 레드-블랙 트리
요소 추가 시 hashCode()로 버킷 위치 계산, equals()로 중복 검증. 버킷 내 요소 8개 초과 시 트리 구조로 변환됩니다.
중복 요소 처리 메커니즘
사용자 정의 객체의 중복 판단을 위해 hashCode()와 equals() 메서드 재정의가 필요합니다.
public class DeduplicationDemo {
public static void main(String[] args) {
Set<Employee> staff = new HashSet<>();
Employee e1 = new Employee("DEV01", 2);
Employee e2 = new Employee("DEV01", 2); // 중복 데이터
staff.add(e1);
staff.add(e2);
System.out.println(staff.size()); // 1
}
}
LinkedHashSet의 순서 유지
삽입 순서 보장이 필요한 경우 LinkedHashSet을 사용하며, 내부적으로 이중 연결 리스트로 순서를 관리합니다.
public class OrderPreservation {
public static void main(String[] args) {
Set<Employee> orderedSet = new LinkedHashSet<>();
orderedSet.add(new Employee("T001", 5));
orderedSet.add(new Employee("T002", 3));
orderedSet.add(new Employee("T003", 7));
// 출력 순서: T001 → T002 → T003
orderedSet.forEach(System.out::println);
}
}