트리 컬렉션의 사용자 정의 순서
Comparator를 TreeMap과 TreeSet에 제공해 도메인에 맞는 정렬 순서를 정의합니다.
트리 컬렉션의 사용자 정의 순서은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
사용자 정의 순서가 필요한 이유
트리 컬렉션(TreeMap, TreeSet)은 기본적으로 자연 순서를 사용합니다. 도메인 객체에 자연 순서가 없거나 다른 정렬이 필요할 때는 생성 시 Comparator를 제공합니다.
TreeMap 생성 시 Comparator 지정
사용자 정의 규칙에 따라 키를 정렬하려면 comparator를 전달합니다. 예를 들어 알파벳 역순으로 정렬할 수 있습니다.
import java.util.*;
TreeMap<String, Integer> map = new TreeMap<>(Comparator.reverseOrder());
map.put("banana", 2);
map.put("apple", 1);
map.put("cherry", 3);
map.forEach((k,v) -> System.out.println(k)); // cherry, banana, appleTreeSet 생성 시 Comparator 지정
요소의 자연 순서와 관계없이 정렬 순서를 제어하려면 TreeSet에 comparator를 제공합니다.
TreeSet<String> byLength = new TreeSet<>(
Comparator.comparingInt(String::length)
.thenComparing(Comparator.naturalOrder())
);
byLength.addAll(List.of("fig","apple","kiwi","date","banana"));
for (String s : byLength) System.out.print(s + " ");
// fig date kiwi apple banana여러 필드로 객체 정렬하기
주요 필드로 정렬한 다음 동률을 해소하기 위해 보조 필드로 정렬하도록 comparator를 연결할 수 있습니다.
record Employee(String name, String dept, int salary) {}
TreeSet<Employee> sorted = new TreeSet<>(
Comparator.comparing(Employee::dept)
.thenComparingInt(Employee::salary).reversed()
.thenComparing(Employee::name)
);
sorted.add(new Employee("Alice", "Eng", 90_000));
sorted.add(new Employee("Bob", "Eng", 85_000));
sorted.add(new Employee("Carol", "HR", 70_000));
for (Employee e : sorted) System.out.println(e.dept()+" "+e.name());equals와의 일관성
중요한 규칙: TreeSet/TreeMap에서 사용하는 comparator가 컬렉션의 동등성을 정의합니다. comparator.compare(a, b) == 0이면 a.equals(b)가 false인 경우에도 a와 b를 같은 키로 간주합니다.
// Comparator ignoring case — "apple" and "APPLE" become the same key!
TreeSet<String> ci = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
ci.add("apple");
ci.add("APPLE"); // not added — same by comparator
System.out.println(ci.size()); // 1대소문자를 구분하지 않는 TreeMap
실무에서 자주 필요한 형태는 키가 대소문자를 구분하지 않는 문자열인 TreeMap입니다(HTTP 헤더와 설정 키에 유용합니다).
TreeMap<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
headers.put("Content-Type", "application/json");
headers.put("content-type", "text/html"); // overwrites!
System.out.println(headers.get("CONTENT-TYPE")); // text/html
System.out.println(headers.size()); // 1Null 안전 Comparator
자연 순서를 사용하는 트리 컬렉션은 null 키에 대해 NPE를 발생시킵니다. null을 최솟값 키로 허용하려면 null을 안전하게 처리하는 comparator를 사용합니다.
TreeMap<String, Integer> map = new TreeMap<>(
Comparator.nullsFirst(Comparator.naturalOrder())
);
map.put(null, 0);
map.put("b", 2);
map.put("a", 1);
map.forEach((k,v) -> System.out.println(k + "=" + v));
// null=0, a=1, b=2도메인 객체 예시: 가격순 Product
TreeSet에서 Product를 가격순으로 정렬하고, 고유성을 유지하기 위한 동률 해소 기준으로 이름을 사용합니다.
record Product(String name, double price) {}
TreeSet<Product> catalog = new TreeSet<>(
Comparator.comparingDouble(Product::price)
.thenComparing(Product::name)
);
catalog.add(new Product("Widget", 9.99));
catalog.add(new Product("Gadget", 24.99));
catalog.add(new Product("Donut", 9.99));
catalog.forEach(p -> System.out.println(p.name() + " $" + p.price()));
// Donut $9.99, Widget $9.99, Gadget $24.99Comparator 가져오기
TreeMap/TreeSet에서 comparator()를 호출하면 사용자 정의 comparator를 가져올 수 있습니다. 자연 순서를 사용하는 경우에는 null을 반환합니다.
TreeMap<String, Integer> map = new TreeMap<>(Comparator.reverseOrder());
System.out.println(map.comparator() != null); // true
TreeMap<String, Integer> natural = new TreeMap<>();
System.out.println(natural.comparator()); // nullComparator 조합
Java의 Comparator는 깔끔한 조합을 위한 연결 가능한 팩토리 메서드를 제공합니다.
Comparator<String> comp =
Comparator.comparingInt(String::length) // by length
.thenComparing(Comparator.naturalOrder()); // then alphabetically
TreeSet<String> ts = new TreeSet<>(comp);
ts.addAll(List.of("go", "java", "c", "rust", "py"));
ts.forEach(s -> System.out.print(s + " "));
// c go py java rust사용자 정의 Comparator를 사용하지 말아야 할 때
TreeMap 키나 TreeSet 요소에 대해 equals와 일관되지 않는 comparator는 사용하지 마십시오. 이러한 comparator는 혼란스러운 누락 항목을 만듭니다. 모든 컬렉션 상황에서 올바르게 동작하도록 compare(a, b) == 0인 경우와 a.equals(b)인 경우가 서로 같도록 하십시오.
빠른 확인
TreeSet이 String::length만을 기준으로 하는 comparator를 사용합니다. "cat"과 "dog"을 모두 add하면 어떻게 되나요?
복습: 사용자 지정 정렬
핵심 내용:
- TreeMap/TreeSet 생성자에 Comparator를 전달하여 사용자 지정 정렬을 정의합니다
- Comparator가 정의하는 동등성이 트리 컬렉션의 고유성을 결정합니다
- 예상하지 못한 결과를 피하려면 Comparator가 equals와 일관되도록 해야 합니다
- null을 안전하게 처리하는 정렬에는 Comparator.nullsFirst/nullsLast를 사용합니다
- 여러 필드를 정렬하려면 thenComparing으로 연결합니다
자주 묻는 질문
“트리 컬렉션의 사용자 정의 순서” 강의는 무료인가요?
네 — “트리 컬렉션의 사용자 정의 순서” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“트리 컬렉션의 사용자 정의 순서”에서 뭘 배우나요?
Comparator를 TreeMap과 TreeSet에 제공해 도메인에 맞는 정렬 순서를 정의합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Java Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“트리 컬렉션의 사용자 정의 순서” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- TreeMap: 정렬된 키-값 쌍
- 부분 맵과 범위 뷰
- TreeSet과 NavigableSet
- 트리 컬렉션의 사용자 정의 순서