firstKey()和lastKey()仅返回排序后首个/末个键(K类型),不返回Entry;空TreeMap调用会抛NoSuchElementException,需判空或改用firstEntry()/lastEntry()。

firstKey() 和 lastKey() 返回的是键本身,不是 Entry
很多人误以为 firstKey() 会返回类似 Map.Entry 的键值对,其实它只返回排序后第一个键的值(K 类型),比如 Integer 或 String。同理 lastKey() 也只返回最大键。要拿到对应的值,得额外调用 get():
-
map.get(map.firstKey())才是第一个键的值 -
map.get(map.lastKey())才是最后一个键的值 - 如果键存在但值为
null,get()也会返回null,无法区分“键不存在”和“值为 null”
空 TreeMap 调用 firstKey() 或 lastKey() 会抛异常
firstKey() 和 lastKey() 在空 TreeMap 上直接调用会触发 NoSuchElementException,不是返回 null。这点和 pollFirstEntry() 不同——后者空时返回 null。
- 安全写法必须先判空:
if (!map.isEmpty()) { ... } - 或者用
firstEntry()/lastEntry(),它们在空时返回null,且一步拿到键值对 - 注意:即使用了
firstEntry(),也要检查返回值是否为null再解包getKey()或getValue()
边界键可能不对应你预期的“范围起点/终点”
如果你本意是取“前 N 个”或“某区间内”,仅靠 firstKey() 和 lastKey() 是不够的。firstKey() 只告诉你最小键是多少,但不提供子集;lastKey() 同理。真正做范围切片得用 subMap()、headMap() 或 tailMap():
-
map.subMap(fromKey, true, toKey, false):闭开区间,含fromKey,不含toKey -
map.headMap(toKey, false):所有键 toKey -
map.tailMap(fromKey, true):所有键 ≥fromKey - 这些方法返回的仍是
SortedMap(底层共享红黑树节点),修改会影响原TreeMap,如需隔离请显式构造新TreeMap
自定义 Comparator 下 firstKey/lastKey 的行为依赖比较逻辑
当 TreeMap 用自定义 Comparator 构造时,firstKey() 返回的是该比较器下“最小”的键,lastKey() 是“最大”的键——这未必符合自然顺序。例如倒序比较器下,firstKey() 实际是数值最大的那个键。
- 务必确认你的
Comparator实现没有逻辑错误(比如漏处理null或违反传递性) - 若键类型本身实现了
Comparable,但又传了反向Comparator,firstKey()就和min(key1,key2,...)直觉相反 - 调试时可打印
map.keySet()全量集合,验证首尾是否符合预期
实际边界操作中,最容易被忽略的是空集合保护和 comparator 语义一致性——前者导致运行时崩溃,后者让 first/last 表现和直觉错位,且难以复现。










