关键看是否需要按键的自然或自定义逻辑顺序:需快速查改删且无序用HashMap(平均O(1),允许null键);需有序遍历、范围查询或排名用TreeMap(O(log n),键须可比较)。

选 HashMap 还是 TreeMap,关键看你要不要“顺序”——不是指插入顺序,而是按键值自然或自定义排序后的逻辑顺序。
需要快速查、改、删,且不关心顺序
用 HashMap。它平均 O(1) 的时间复杂度在高频读写场景下优势明显。
- 缓存用户会话(用 userId 作 key,查得越快越好)
- 构建索引映射(比如文件名 → 文件路径)
- 键可能为 null(HashMap 允许一个 null 键,TreeMap 会直接抛 NullPointerException)
- 键对象已正确重写 hashCode() 和 equals()(否则 HashMap 行为异常)
需要按键有序遍历、范围查询或排名
用 TreeMap。它不是“排好序再遍历”,而是插入时就维持红黑树结构,遍历时天然有序,还能高效做子范围操作。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 成绩表按分数升序/降序展示(
new TreeMap((a, b) -> b - a)实现倒序) - 统计某分数段学生:
map.subMap(80, true, 90, true) - 获取最小键、最大键:
map.firstKey()/map.lastKey() - 键必须可比较:要么实现 Comparable,要么构造时传 Comparator
想保持插入顺序?别选 TreeMap
TreeMap 排的是键的大小顺序,和你 put 的先后无关。如果要按插入顺序迭代,该用 LinkedHashMap。
- 日志记录按时间先后展示(插入即顺序)
- LruCache 实现(启用 access-order 模式)
- 它性能接近 HashMap,又比 TreeMap 快,还带顺序保障
多线程环境下怎么办
两者都不安全。别用 Collections.synchronizedMap 包一层应付了事——它只是方法加锁,吞吐低。
- 读多写少 + 需要顺序 → 用 ConcurrentSkipListMap(底层跳表,线程安全且有序)
- 读多写少 + 不需要顺序 → 用 ConcurrentHashMap
- 写操作频繁且需强一致性 → 考虑业务层加锁或用外部同步机制

















