map是java中实现key唯一、key→value单向映射的接口;hashmap要求key重写hashcode()和equals()以保证查找正确,禁止修改影响哈希值的字段;treemap要求key可比较且不允null key;遍历时应优先用entryset(),避免边遍历边remove()或误用values()视图。

Map 接口本质是 Java 里专干“查字典”这事的工具:给一个 key,立刻拿到对应的 value;同一个 key 只能存一次,重复 put() 就是覆盖,不是报错。
为什么 HashMap 的 key 必须重写 hashCode() 和 equals()
因为 HashMap 查找靠哈希值定位桶位置,再用 equals() 确认是不是真要找的那个 key。如果只重写 equals() 不重写 hashCode(),两个逻辑相等的对象可能被分到不同桶里,get() 就永远找不到它。
- 自定义类作 key 时,IDE 通常会提示生成这两个方法——别跳过
- 用
String、Integer等 JDK 自带类型当 key 是安全的,它们已正确实现 - 如果 key 对象在放入 map 后修改了影响
hashCode()的字段(比如改了某个成员变量),之后就再也get()不出来了——key实际上“失联”了
HashMap vs TreeMap:选哪个不只看排序
表面看 TreeMap 能按 key 排序,HashMap 更快;但背后约束差别很大:
-
HashMap允许null作为 key(仅一个)和任意多个nullvalue;TreeMap不允许nullkey(会抛NullPointerException),但 value 可为null -
TreeMap要求 key 实现Comparable接口,或构造时传入Comparator;HashMap没这要求 - 遍历时:
HashMap顺序不确定(JDK 8 后是插入顺序的近似,但不保证);LinkedHashMap才真正保插入序;TreeMap按 key 自然序或比较器序
遍历 Map 时最容易误用的三种写法
不是语法错,而是性能或逻辑隐患明显:
- 用
keySet()遍历后再调get():对大 map 是 O(n) × O(1) 查找,但实际触发多次哈希计算,不如直接用entrySet() - 边遍历边
remove():不通过Iterator.remove()会抛ConcurrentModificationException;for-each循环里直接map.remove(key)就是典型错误 - 把
values()当 List 用:返回的是Collection<v></v>视图,不支持add()、remove()(除非底层 map 支持且实现允许),且没有索引访问能力
Map 不是集合容器,它不继承 Collection,所以别下意识套用 list/set 的操作习惯;它的核心契约就两条:key 唯一、key→value 单向映射。其余所有行为——是否允许 null、是否有序、线程安全与否——全看具体实现类怎么定,不能想当然。










