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 своими словами; примеры кода — авторские.