TreeMap
TreeMap — класс из пакета java.util, реализующий интерфейс NavigableMap. Хранит пары «ключ — значение» в красно-чёрном дереве, поэтому ключи всегда упорядочены — либо по их естественному порядку (Comparable), либо по переданному компаратору.
В отличие от HashMap, перебор TreeMap идёт в отсортированном порядке ключей. Операции put, get, remove выполняются за логарифмическое время.
TreeMap не допускает null-ключи (если только компаратор это явно не разрешает), но допускает null-значения. Не является потокобезопасным.
Зачем нужен
Когда нужен быстрый доступ к минимальному/максимальному ключу.
Когда нужно перебирать пары в отсортированном порядке.
Когда нужны диапазонные запросы: ключи в интервале, «ближайший снизу», «ближайший сверху».
Конструкторы
TreeMap()— пустая карта, ключи сортируются по естественному порядку.TreeMap(Comparator<? super K> c)— пустая карта с заданным компаратором.TreeMap(Map<? extends K, ? extends V> m)— карта с элементами из другой Map.TreeMap(SortedMap<K, ? extends V> m)— копия отсортированной карты, сохраняет компаратор.
Популярные методы
put(K key, V value)/get(Object key)/remove(Object key).firstKey()/lastKey()— наименьший и наибольший ключ.firstEntry()/lastEntry()— соответствующие пары.floorKey(K key)/ceilingKey(K key)— ближайший ключ<=или>=заданного.lowerKey(K key)/higherKey(K key)— строго<или>.headMap(K toKey),tailMap(K fromKey),subMap(K from, K to)— представления с диапазоном.keySet(),values(),entrySet(),size().
Пример 1. Сортировка ключей
import java.util.TreeMap;
public class Sorted {
public static void main(String[] args) {
TreeMap<String, Integer> map = new TreeMap<>();
map.put("ESP32", 30);
map.put("Arduino", 14);
map.put("RaspberryPi", 40);
for (var e : map.entrySet()) {
System.out.println(e.getKey() + " -> " + e.getValue());
}
}
}
Вывод:
Arduino -> 14
ESP32 -> 30
RaspberryPi -> 40
Пример 2. Min / max ключа
import java.util.TreeMap;
public class MinMax {
public static void main(String[] args) {
TreeMap<Integer, String> map = new TreeMap<>();
map.put(5, "five");
map.put(2, "two");
map.put(9, "nine");
map.put(1, "one");
System.out.println("first: " + map.firstKey() + " -> " + map.get(map.firstKey()));
System.out.println("last: " + map.lastKey() + " -> " + map.get(map.lastKey()));
}
}
Вывод:
first: 1 -> one
last: 9 -> nine
Пример 3. Поиск ближайшего ключа
import java.util.TreeMap;
public class Nearest {
public static void main(String[] args) {
TreeMap<Integer, String> map = new TreeMap<>();
map.put(10, "A");
map.put(20, "B");
map.put(30, "C");
map.put(40, "D");
System.out.println("floor(25): " + map.floorKey(25));
System.out.println("ceiling(25): " + map.ceilingKey(25));
System.out.println("lower(20): " + map.lowerKey(20));
System.out.println("higher(20): " + map.higherKey(20));
}
}
Вывод:
floor(25): 20
ceiling(25): 30
lower(20): 10
higher(20): 30
Пример 4. Диапазонные представления
import java.util.TreeMap;
public class RangeViews {
public static void main(String[] args) {
TreeMap<Integer, String> map = new TreeMap<>();
for (int i = 1; i <= 6; i++) map.put(i * 10, "v" + i);
System.out.println("headMap(30): " + map.headMap(30));
System.out.println("tailMap(40): " + map.tailMap(40));
System.out.println("subMap(20,50): " + map.subMap(20, 50));
}
}
Вывод:
headMap(30): {10=v1, 20=v2}
tailMap(40): {40=v4, 50=v5, 60=v6}
subMap(20,50): {20=v2, 30=v3, 40=v4}
Пример 5. Свой компаратор — обратный порядок
import java.util.Comparator;
import java.util.TreeMap;
public class ReverseOrder {
public static void main(String[] args) {
TreeMap<Integer, String> map = new TreeMap<>(Comparator.reverseOrder());
map.put(1, "one");
map.put(3, "three");
map.put(2, "two");
System.out.println(map);
}
}
Вывод:
{3=three, 2=two, 1=one}
Пример 6. Подсчёт частоты с упорядоченным результатом
import java.util.TreeMap;
public class FrequencyCount {
public static void main(String[] args) {
String text = "alash arduino esp32 alash arduino alash";
TreeMap<String, Integer> freq = new TreeMap<>();
for (String w : text.split(" ")) {
freq.merge(w, 1, Integer::sum);
}
System.out.println(freq);
}
}
Вывод:
{alash=3, arduino=2, esp32=1}
Пример 7. Расписание калибровки датчиков
import java.util.TreeMap;
public class Schedule {
public static void main(String[] args) {
TreeMap<Integer, String> events = new TreeMap<>();
events.put(100, "init");
events.put(500, "read_line");
events.put(1000, "calibrate");
events.put(2000, "save");
int now = 600;
Integer next = events.ceilingKey(now);
System.out.println("Сейчас " + now + " ms, ближайшее событие: " + next + " -> " + events.get(next));
}
}
Вывод:
Сейчас 600 ms, ближайшее событие: 1000 -> calibrate
Пример 8. Удаление и проверка размера
import java.util.TreeMap;
public class RemoveEntries {
public static void main(String[] args) {
TreeMap<String, Integer> map = new TreeMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
map.remove("b");
System.out.println(map);
System.out.println("Размер: " + map.size());
}
}
Вывод:
{a=1, c=3}
Размер: 2
См. также
Примечание
Описание основано на официальной документации Oracle Java SE 21 API (https://docs.oracle.com/en/java/javase/21/docs/api/). Материал распространяется на условиях Oracle Free Documentation License. Тексты статьи написаны редакцией AlashEd своими словами; примеры кода — авторские.