Java TreeMap 마스터: 실전 예제로 배우는 정렬 맵
Java TreeMap
Java TreeMap 클래스 – 강력하고 자연 정렬되는 맵 구현체 – 를 명확한 예제, 핵심 연산, 고급 탐색 기법과 함께 탐구합니다.
TreeMap 클래스는 Java 컬렉션 프레임워크의 일부로, 키의 자연 순서나 커스텀 Comparator에 따라 엔트리를 정렬 상태로 유지하는 레드-블랙 트리 구현을 제공합니다. NavigableMap 인터페이스를 구현하여 맵 순회와 쿼리를 위한 편리한 메서드를 추가합니다.
TreeMap 생성하기
TreeMap 사용 전 패키지 임포트:
import java.util.TreeMap;
인스턴스 생성:
TreeMap<Key, Value> numbers = new TreeMap<>();
기본적으로 키는 자연 오름차순으로 정렬. 커스텀 순서 필요 시 생성자에 Comparator 전달.
- Key – 각 엔트리의 고유 식별자
- Value – 키와 연관된 데이터
TreeMap 메서드 개요
이 클래스는 풍부한 연산 세트를 제공합니다. 주요 카테고리와 코드 스니펫을 다룹니다.
요소 삽입
put() – 키/값 쌍 추가 또는 교체
putAll() – 다른 맵 병합
putIfAbsent() – 키가 없을 때만 삽입
예제:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> evenNumbers = new TreeMap<>();
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);
evenNumbers.putIfAbsent("Six", 6);
System.out.println("TreeMap of even numbers: " + evenNumbers);
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("One", 1);
numbers.putAll(evenNumbers);
System.out.println("TreeMap of numbers: " + numbers);
}
}
출력
TreeMap of even numbers: {Four=4, Six=6, Two=2} TreeMap of numbers: {Four=4, One=1, Six=6, Two=2}
요소 접근
컬렉션 뷰 사용
entrySet() – 모든 키/값 쌍 반환
keySet() – 모든 키 반환
values() – 모든 값 반환
예제:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("TreeMap: " + numbers);
System.out.println("Key/Value mappings: " + numbers.entrySet());
System.out.println("Keys: " + numbers.keySet());
System.out.println("Values: " + numbers.values());
}
}
출력
TreeMap: {One=1, Three=3, Two=2} Key/Value mappings: [One=1, Three=3, Two=2] Keys: [One, Three, Two] Values: [1, 3, 2]
값 검색
get() – 키의 값 반환, 없으면 null
getOrDefault() – 키 없으면 기본값 반환
예제:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("TreeMap: " + numbers);
int value1 = numbers.get("Three");
System.out.println("Using get(): " + value1);
int value2 = numbers.getOrDefault("Five", 5);
System.out.println("Using getOrDefault(): " + value2);
}
}
출력
TreeMap: {One=1, Three=3, Two=2} Using get(): 3 Using getOrDefault(): 5
엔트리 제거
remove(key) – 엔트리 삭제하고 값 반환
remove(key, value) – 키가 지정된 값에 매핑될 때만 삭제
예제:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("TreeMap: " + numbers);
int removed = numbers.remove("Two");
System.out.println("Removed value: " + removed);
boolean removedPair = numbers.remove("Three", 3);
System.out.println("Is the entry {Three=3} removed? " + removedPair);
System.out.println("Updated TreeMap: " + numbers);
}
}
출력
TreeMap: {One=1, Three=3, Two=2} Removed value: 2 Is the entry {Three=3} removed? true Updated TreeMap: {One=1}
값 교체
replace(key, value) – 키의 값 업데이트
replace(key, old, new) – 현재 값이 old와 일치할 때만 업데이트
replaceAll(function) – 모든 엔트리에 함수 적용
예제:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
System.out.println("Original TreeMap: " + numbers);
numbers.replace("Second", 22);
numbers.replace("Third", 3, 33);
System.out.println("After replace(): " + numbers);
numbers.replaceAll((k, v) -> v + 2);
System.out.println("After replaceAll(): " + numbers);
}
}
출력
Original TreeMap: {First=1, Second=2, Third=3} After replace(): {First=1, Second=22, Third=33} After replaceAll(): {First=3, Second=24, Third=35}
탐색 메서드
TreeMap은 NavigableMap을 구현하므로 구조를 효율적으로 쿼리하는 메서드를 제공합니다.
첫 번째와 마지막 요소
firstKey() – 순서상 첫 키
firstEntry() – 첫 키의 엔트리
lastKey() – 마지막 키
lastEntry() – 마지막 키의 엔트리
예제:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
System.out.println("TreeMap: " + numbers);
System.out.println("First Key: " + numbers.firstKey());
System.out.println("Last Key: " + numbers.lastKey());
System.out.println("First Entry: " + numbers.firstEntry());
System.out.println("Last Entry: " + numbers.lastEntry());
}
}
출력
TreeMap: {First=1, Second=2, Third=3} First Key: First Last Key: Third First Entry: First=1 Last Entry: Third=3
Ceiling, Floor, Higher, Lower
이 메서드들은 주어진 키에 상대적인 키나 엔트리를 반환하여 범위 쿼리를 용이하게 합니다.
higherKey(), higherEntry() – 다음 더 높은 키/엔트리
lowerKey(), lowerEntry() – 이전 더 낮은 키/엔트리
ceilingKey(), ceilingEntry() – 주어진 키 이상인 가장 작은 키/엔트리
floorKey(), floorEntry() – 주어진 키 이하인 가장 큰 키/엔트리
예제:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 5);
numbers.put("Third", 4);
numbers.put("Fourth", 6);
System.out.println("TreeMap: " + numbers);
System.out.println("higherKey('Fourth'): " + numbers.higherKey("Fourth"));
System.out.println("higherEntry('Fourth'): " + numbers.higherEntry("Fourth"));
System.out.println("lowerKey('Fourth'): " + numbers.lowerKey("Fourth"));
System.out.println("lowerEntry('Fourth'): " + numbers.lowerEntry("Fourth"));
System.out.println("ceilingKey('Fourth'): " + numbers.ceilingKey("Fourth"));
System.out.println("ceilingEntry('Fourth'): " + numbers.ceilingEntry("Fourth"));
System.out.println("floorKey('Fourth'): " + numbers.floorKey("Fourth"));
System.out.println("floorEntry('Fourth'): " + numbers.floorEntry("Fourth"));
}
}
출력
TreeMap: {First=1, Fourth=6, Second=5, Third=4} higherKey('Fourth'): Second higherEntry('Fourth'): Second=5 lowerKey('Fourth'): First lowerEntry('Fourth'): First=1 ceilingKey('Fourth'): Fourth ceilingEntry('Fourth'): Fourth=6 floorKey('Fourth'): Fourth floorEntry('Fourth'): Fourth=6
폴링과 범위
pollFirstEntry()와 pollLastEntry()는 각각 첫/마지막 엔트리를 제거하고 반환합니다.
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
System.out.println("TreeMap: " + numbers);
System.out.println("pollFirstEntry(): " + numbers.pollFirstEntry());
System.out.println("pollLastEntry(): " + numbers.pollLastEntry());
System.out.println("Updated TreeMap: " + numbers);
}
}
출력
TreeMap: {First=1, Second=2, Third=3} pollFirstEntry(): First=1 pollLastEntry(): Third=3 Updated TreeMap: {Second=2}
headMap, tailMap, subMap
이 메서드들은 특정 키 범위에 대한 뷰를 제공합니다.
headMap(toKey, inclusive) – 키 < toKey (포함 시 ≤)
tailMap(fromKey, inclusive) – 키 ≥ fromKey (배제 시 >)
subMap(fromKey, fromInclusive, toKey, toInclusive) – 두 경계 사이의 키
예제:
import java.util.TreeMap;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
numbers.put("Fourth", 4);
System.out.println("TreeMap: " + numbers);
System.out.println("headMap('Fourth'): " + numbers.headMap("Fourth"));
System.out.println("headMap('Fourth', true): " + numbers.headMap("Fourth", true));
System.out.println("tailMap('Second'): " + numbers.tailMap("Second"));
System.out.println("tailMap('Second', false): " + numbers.tailMap("Second", false));
System.out.println("subMap('Fourth', true, 'Third', false): " + numbers.subMap("Fourth", true, "Third", false));
}
}
출력
TreeMap: {First=1, Fourth=4, Second=2, Third=3} headMap('Fourth'): {First=1} headMap('Fourth', true): {First=1, Fourth=4} tailMap('Second'): {Second=2, Third=3, Fourth=4} tailMap('Second', false): {Third=3, Fourth=4} subMap('Fourth', true, 'Third', false): {Fourth=4, Second=2}
추가 유틸리티 메서드
| 메서드 | 설명 |
clone() | 맵의 얕은 복사본 생성 |
containsKey() | 키 존재 여부 확인 |
containsValue() | 특정 값 존재 확인 |
size() | 엔트리 수 반환 |
clear() | 모든 엔트리 제거 |
Comparator로 커스텀 키 정렬
키를 다르게 정렬하려면(역순, 대소문자 무시 등) Comparator를 구현하여 TreeMap 생성자에 전달하세요.
import java.util.TreeMap;
import java.util.Comparator;
class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>(new CustomComparator());
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
numbers.put("Fourth", 4);
System.out.println("TreeMap: " + numbers);
}
static class CustomComparator implements Comparator<String> {
@Override
public int compare(String a, String b) {
// 자연 순서 역전
return a.compareTo(b) * -1;
}
}
}
출력
TreeMap: {Third=3, Second=2, Fourth=4, First=1}
Comparator에 대한 더 많은 내용은 공식 Java 문서를 참조하세요.