프로젝트 중 느낀 자바 기초의 부족함을 보완하고자 핵심 주제를 순차적으로 복습할 예정입니다.
자바 코어 → 자바 스레드 → 자바 OOP → 자바의 예외 → 자바의 컬렉션 → 최대 절전 모드 순으로 정리할 예정입니다.
자바 컬렉션 - 정렬 · 비교
- Comparable 인터페이스란?
- Comparator 인터페이스란?
- Comparable과 Comparator의 차이점은 무엇입니까?
- HashSet과 TreeSet의 차이점은 무엇입니까?
Comparable 인터페이스란?
Comparable은 객체가 자기 자신만의 자연 순서를 정의하도록 compareTo를 구현하게 하는 인터페이스이며, 컬렉션·배열 정렬 시 기본 기준이 됩니다. compareTo(a,b)==0이면 a.equals(b)도 true여야 한다는 계약을 지켜야 하고, 이를 어길 경우 SortedSet 내부에서 같은 키로 인식해도 해시나 리스트에서는 별도 객체로 남아 “유령 항목” 문제가 발생할 수 있습니다. JDK 17 레코드와 함께 implements Comparable 선언 후 Comparator.comparing 체인을 사용하면 불변 데이터 캐리어를 간결하게 구현할 수 있습니다.
public record Person(String name, int age) implements Comparable<Person> {
@Override
public int compareTo(Person o) {
return Comparator
.comparingInt(Person::age) // 나이 오름차순
.thenComparing(Person::name) // 동갑이면 이름
.compare(this, o);
}
}
List<Person> list = List.of(new Person("Tom", 30), new Person("Ann", 25));
List<Person> sorted = new ArrayList<>(list);
Collections.sort(sorted); // 자연 순서로 정렬
Comparator 인터페이스란?
Comparator는 외부에서 두 객체를 비교하는 전략을 캡슐화하며, thenComparing 체인으로 다중 정렬 기준을 손쉽게 조합할 수 있습니다. 상태를 주입해 런타임에 기준을 교체할 수 있다는 점이 특징입니다. String::compareToIgnoreCase나 Comparator.comparing(String::length) 같은 메서드 참조를 쓰면 람다보다 의도가 명확해지고 JIT 인라이닝 힌트도 얻을 수 있습니다. 또한 thenComparing·reversed가 디폴트 메서드로 구현돼 불필요한 익명 객체를 줄여 GC 부담을 완화합니다.
Comparable과 Comparator의 차이점은 무엇입니까?
Comparable은 객체 내부 기준을 한 가지만 가질 수 있는 반면, Comparator는 외부 기준으로 원하는 만큼 정의할 수 있어 OCP 원칙에 더 부합합니다. 예를 들어 new TreeSet<>(comparator)와 같이 TreeSet·TreeMap 생성자에 비교자를 주입하면 요소 클래스가 Comparable을 구현하지 않아도 정렬 트리에 삽입할 수 있습니다. 또한 Arrays.sort는 기본형 배열에 퀵소트, 객체 배열에 TimSort를 쓰며, 비교자 오버로드가 존재하면 TimSort가 그 비교자를 호출해 정렬합니다.
HashSet과 TreeSet의 차이점은 무엇입니까?
HashSet은 해시 기반으로 평균 연산이 O(1)이며 순서를 보장하지 않고 null을 하나 허용합니다. 다만 해시 충돌이 많으면 버킷이 연결 리스트나 트리 구조로 변해 O(1)이 O(log N)까지 악화될 수 있는데, 자바 8 이상에서는 충돌 임계치를 넘으면 내부 버킷을 작은 레드블랙트리로 전환해 최악 성능을 완화합니다. 반대로 TreeSet은 레드블랙트리로 구현돼 O(log N) 성능 대신 자동 정렬과 ceiling·floor 등 NavigableSet 범위 연산을 제공합니다. 단 null은 허용하지 않습니다. 따라서 속도가 우선시 되면 HashSet을 사용하고, 데이터가 항상 정렬되어 있어야 하거나 범위 및 근사치 조회가 자주 필요하다면 TreeSet을 사용하는 것이 좋습니다.
Set<Integer> hash = new HashSet<>();
hash.add(null); // 허용
hash.addAll(List.of(3,1,2));
System.out.println(hash); // 순서 보장 없음
Set<Integer> tree = new TreeSet<>();
// tree.add(null); // NPE 발생 → 주석 해제 시 확인
tree.addAll(List.of(3,1,2));
System.out.println(tree); // [1, 2, 3] 자동 정렬
'Java' 카테고리의 다른 글
자바 최대 절전 모드 (2) - 구성 · 코어 API · 운영 (0) | 2025.07.10 |
---|---|
자바 최대 절전 모드 (1) - ORM 및 기본 개념 (0) | 2025.07.10 |
자바 컬렉션 (4) – 반복자 · 열거 (0) | 2025.07.02 |
자바 컬렉션 (3) – 구현 클래스 (0) | 2025.07.02 |
자바 컬렉션 (2) – 핵심 인터페이스 (0) | 2025.07.02 |