在Java中如何遍历TreeMap集合_Java有序映射遍历解析

TreeMap遍历本质是中序遍历红黑树,天然按键升序;四种方式:keySet()、values()、entrySet()(最常用)、Iterator(唯一安全修改方式);遍历时仅允许entry.setValue()或Iterator.remove(),禁止直接put/remove。

TreeMap 遍历本质是遍历红黑树的中序序列

TreeMap 底层是红黑树,所以它的 keySet()entrySet()values() 返回的集合天然按 key 升序排列。遍历时不需要额外排序,但也不能用基于哈希的随机访问方式(比如通过索引),所有遍历都必须走迭代器或增强 for 循环。

四种常用遍历方式及适用场景

实际开发中主要用以下四种,区别在于是否需要 key、value 或 entry,以及是否需修改映射:

  • 只读 key:用 for (K key : map.keySet()) —— 简洁,但每次 map.get(key) 是 O(log n) 查找,不推荐频繁取 value
  • 只读 value:用 for (V value : map.values()) —— 无法反查 key,且顺序由 key 决定,不是 value 自身大小顺序
  • 同时读 key 和 value(最常用):for (Map.Entry e : map.entrySet()) —— 一次拿到键值对,O(1) 访问,性能最优
  • 需要修改 value 或删除当前项:必须用 Iterator>,调用 iterator.remove() 安全删除,否则抛 ConcurrentModificationException

遍历时修改元素的正确姿势

TreeMap 不允许在遍历中直接调用 map.put()map.remove(),否则触发快速失败机制。唯一安全的修改方式是:

  • 仅更新 value:通过 entry.setValue(newVal) —— 这不会破坏红黑树结构
  • 删除当前项:必须用 Iterator.remove(),不能用 map.remove(key)
  • 插入新 key:禁止在遍历中执行,应先收集待插入项,遍历结束后统一 putAll()
TreeMap map = new TreeMap<>();
map.put("a", 1);
map.put("b", 2);
Iterator> it = map.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry e = it.next();
    if (e.getKey().equals("a")) {
        e.setValue(99); // ✅ 允许
        it.remove();    // ✅ 安全删除
    }
}

注意 reverseOrder() 和自定义 Comparator 的影响

TreeMap 构造时若传入 Comparator(包括 Collections.reverseOrder()),遍历顺序完全由该比较器决定,和自然顺序无关。此时:

  • firstKey() / lastKey() 返回的是比较器下的极值,不是字典序首尾
  • 使用 subMap(from, to) 等范围视图时,from/to 必须符合同一比较逻辑

    ,否则行为未定义
  • 遍历性能仍是 O(n log n),但常数略高(每次比较调用额外函数)

如果只是临时逆序遍历,更轻量的做法是用 new TreeMap(Collections.reverseOrder()).putAll(original),而不是在原 map 上强加 comparator 后再遍历。