0Pricing
Java Academy · 课时

TreeMap:有序键值对

使用 TreeMap 维护有序关系,并通过 firstKey、lastKey、floorKey 和 ceilingKey 进行导航

TreeMap:有序键值对 是 CoddyKit 上的免费 Java Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

什么是 TreeMap?

TreeMap 是一种由红黑树支持的有序映射实现。键按升序自然顺序(或自定义 Comparator 顺序)维护。所有基本操作的复杂度均为 O(log n)。

import java.util.TreeMap;

TreeMap<String, Integer> scores = new TreeMap<>();
scores.put("Charlie", 85);
scores.put("Alice", 92);
scores.put("Bob", 78);

// Iteration is in key order: Alice, Bob, Charlie
for (var entry : scores.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

firstKey、lastKey、floorKey、ceilingKey

TreeMap 的 NavigableMap 接口提供了导航方法,用于查找相对于给定值的键:

TreeMap<Integer, String> map = new TreeMap<>();
map.put(10, "ten"); map.put(20, "twenty"); map.put(30, "thirty"); map.put(40, "forty");

System.out.println(map.firstKey());       // 10
System.out.println(map.lastKey());        // 40
System.out.println(map.floorKey(25));     // 20 (largest key ≤ 25)
System.out.println(map.ceilingKey(25));   // 30 (smallest key ≥ 25)
System.out.println(map.lowerKey(20));     // 10 (strictly less)
System.out.println(map.higherKey(20));    // 30 (strictly greater)

导航 Entry

floorEntry、ceilingEntry、firstEntry 和 lastEntry 返回完整的 Map.Entry,而不只是键:

TreeMap<Integer, String> prices = new TreeMap<>();
prices.put(100, "Budget"); prices.put(300, "Standard"); prices.put(700, "Premium");

var entry = prices.floorEntry(350);
System.out.println(entry.getKey() + ": " + entry.getValue()); // 300: Standard

var top = prices.lastEntry();
System.out.println(top.getValue()); // Premium

subMap、headMap、tailMap

从 TreeMap 中提取范围视图。这些视图由原始映射支持——一方的更改会反映到另一方。

TreeMap<Integer, String> map = new TreeMap<>();
for (int i = 1; i <= 10; i++) map.put(i, "v"+i);

// Keys from 3 (inclusive) to 7 (exclusive)
System.out.println(map.subMap(3, 7));   // {3=v3, 4=v4, 5=v5, 6=v6}

// Keys strictly less than 5
System.out.println(map.headMap(5));     // {1=v1, 2=v2, 3=v3, 4=v4}

// Keys >= 7
System.out.println(map.tailMap(7));     // {7=v7, 8=v8, 9=v9, 10=v10}

包含和排除边界

请使用重载版本来精细控制边界:

TreeMap<Integer, String> map = new TreeMap<>();
for (int i = 1; i <= 10; i++) map.put(i*10, "v"+i);

// From 30 (inclusive) to 60 (inclusive)
System.out.println(map.subMap(30, true, 60, true));
// {30=v3, 40=v4, 50=v5, 60=v6}

降序

使用 descendingMap() 或 descendingKeySet(),以逆序遍历键:

TreeMap<String, Integer> tm = new TreeMap<>();
tm.put("A", 1); tm.put("C", 3); tm.put("B", 2);

for (String key : tm.descendingKeySet()) {
    System.out.print(key + " "); // C B A
}

pollFirstEntry 与 pollLastEntry

以原子方式移除并返回第一个或最后一个 Entry——这对于构建优先级映射很有用:

TreeMap<Integer, String> events = new TreeMap<>();
events.put(8, "Breakfast");
events.put(12, "Lunch");
events.put(18, "Dinner");

var first = events.pollFirstEntry(); // removes 8=Breakfast
System.out.println(first.getValue() + " removed");
System.out.println(events.firstKey()); // 12

使用场景:排行榜

排行榜需要按照得分对玩家进行排序。TreeMap 会自动按键排序:

TreeMap<Integer, String> leaderboard = new TreeMap<>(Comparator.reverseOrder());
leaderboard.put(1200, "Alice");
leaderboard.put(1500, "Bob");
leaderboard.put(900, "Carol");

int rank = 1;
for (var e : leaderboard.entrySet()) {
    System.out.println(rank++ + ". " + e.getValue() + " (" + e.getKey() + ")");
}
// 1. Bob (1500)
// 2. Alice (1200)
// 3. Carol (900)

使用场景:事件调度器

将时间戳映射到事件——使用 ceilingEntry 查找给定时间之后安排的下一个事件:

import java.time.LocalTime;
TreeMap<LocalTime, String> schedule = new TreeMap<>();
schedule.put(LocalTime.of(9,0), "Standup");
schedule.put(LocalTime.of(14,0), "Review");
schedule.put(LocalTime.of(17,0), "Retro");

LocalTime now = LocalTime.of(11, 30);
var next = schedule.ceilingEntry(now);
System.out.println("Next: " + next.getValue()); // Review

TreeMap 与 HashMap 的性能

关键比较:

  • HashMap:get/put 平均为 O(1);无序
  • TreeMap:get/put 为 O(log n);按键排序
  • LinkedHashMap:平均为 O(1);按插入顺序排列

当需要有序键或范围查询时,请使用 TreeMap。对于简单的键查找,HashMap 更快。

线程安全

TreeMap 不是线程安全的(NOT)。对于并发访问,请使用 ConcurrentSkipListMap;它同样能以 O(log n) 的操作复杂度维护有序性,并支持并发读写。

快速检查

有一个键为 {10, 20, 30, 40} 的 TreeMap<Integer, String>。map.floorKey(25) 会返回什么?

回顾:TreeMap

要点:

  • TreeMap 通过红黑树以有序(升序)方式维护键
  • 所有操作的复杂度均为 O(log n)
  • 导航方法:firstKey、lastKey、floorKey、ceilingKey、lowerKey、higherKey
  • 范围视图:subMap、headMap、tailMap(由原映射支持的视图)
  • 对于线程安全的有序映射,请使用 ConcurrentSkipListMap

常见问题解答

「TreeMap:有序键值对」课时是免费的吗?

是的 — 「TreeMap:有序键值对」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「TreeMap:有序键值对」这节课中我会学到什么?

使用 TreeMap 维护有序关系,并通过 firstKey、lastKey、floorKey 和 ceilingKey 进行导航 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「TreeMap:有序键值对」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. TreeMap:有序键值对
  2. 子映射与范围视图
  3. TreeSet 与 NavigableSet
  4. Tree 集合中的自定义排序
← 返回 Java Academy