一、Map 接口通用核心方法(所有实现类均继承)

先统一梳理 Map 接口的基础方法,按功能分类,便于理解各实现类方法的底层逻辑:

方法分类核心方法方法作用
基础 CRUDV put(K key, V value)插入/替换键值对:键存在则替换值,返回旧值;键不存在则插入,返回 null
V putIfAbsent(K key, V value)原子插入:仅当键不存在时插入,返回 null;键存在则返回现有值(JDK8+)
V get(Object key)根据键取值:键不存在返回 null
V getOrDefault(Object key, V defaultValue)根据键取值:键不存在返回默认值(JDK8+)
V remove(Object key)删除键值对:返回被删除的值,键不存在返回 null
boolean remove(Object key, Object value)条件删除:仅当键对应值等于指定值时删除,返回是否成功(JDK8+)
V replace(K key, V value)替换:仅当键存在时替换值,返回旧值;键不存在返回 null
boolean replace(K key, V oldValue, V newValue)条件替换:仅当键对应旧值匹配时替换,返回是否成功
void clear()清空所有键值对
批量操作void putAll(Map<? extends K, ? extends V> m)批量插入另一个 Map 的所有键值对
boolean containsKey(Object key)判断是否包含指定键
boolean containsValue(Object value)判断是否包含指定值(遍历所有值,效率低)
视图操作Set<K> keySet()返回所有键的 Set 视图(修改视图会同步修改原 Map)
Collection<V> values()返回所有值的 Collection 视图(同上)
Set<Map.Entry<K, V>> entrySet()返回键值对 Entry 的 Set 视图(遍历 Map 的最优方式)
辅助操作int size()返回键值对数量
boolean isEmpty()判断是否为空
boolean equals(Object o)判断两个 Map 的键值对完全相等
int hashCode()返回 Map 的哈希值(基于所有 Entry 的哈希值)
JDK8+ 函数式V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)计算并更新键的值:函数接收键和旧值,返回新值(null 则删除该键)
V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)仅当键不存在/值为 null 时,通过函数计算值并插入(实现懒加载)
V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)仅当键存在且值非 null 时,计算并更新值
V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)合并值:键不存在则插入,存在则通过函数合并新旧值(null 则删除)

二、各 Map 实现类详解(特性+特有方法)

1. HashMap(通用型)

核心特性(复用前文,精简)
  • 底层:JDK1.8=数组+链表+红黑树;非线程安全;无序;允许 1 个 null 键、多个 null 值;平均 O(1) 性能。
特有/重写方法(无特有方法,仅重写通用方法)
  • 重写 hash(Object key):计算键的哈希值(JDK1.8 优化:(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16)),减少哈希冲突。
  • 重写 getNode(int hash, Object key):核心查询方法,先定位数组索引,再遍历链表/红黑树找键。
方法使用注意
  • put(null, value):null 键的哈希值固定为 0,存入数组索引 0 位置。
  • 遍历推荐 entrySet(),避免 keySet()+get() 重复计算哈希。

2. LinkedHashMap(有序 HashMap 子类)

核心特性
  • 底层:HashMap+双向链表;非线程安全;支持插入/访问顺序;允许 null 键值;略低于 HashMap 性能。
特有方法/重写方法
特有/重写方法作用
protected boolean removeEldestEntry(Map.Entry<K, V> eldest)可重写方法:返回 true 时移除最老的 Entry(实现 LRU 缓存核心)
构造方法 LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)accessOrder=true 开启访问顺序(get/put 后元素移到链表尾部),默认 false(插入顺序)
方法使用示例(LRU 缓存)
// 最多缓存5个元素,超过则移除最老的
LinkedHashMap<String, Integer> lruMap = new LinkedHashMap<>(16, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry<String, Integer> eldest) {
        return size() > 5;
    }
};

3. TreeMap(有序排序)

核心特性
  • 底层:红黑树;非线程安全;按键自然/定制排序;自然排序不允许 null 键;O(logn) 性能。
特有方法(导航/排序相关)
特有方法作用
K firstKey()返回最小键(红黑树最左节点)
K lastKey()返回最大键(红黑树最右节点)
K ceilingKey(K key)返回≥key 的最小键,无则返回 null
K floorKey(K key)返回≤key 的最大键,无则返回 null
K higherKey(K key)返回>key 的最小键,无则返回 null
K lowerKey(K key)返回<key 的最大键,无则返回 null
NavigableSet<K> navigableKeySet()返回可导航的键 Set(支持逆序、范围查询)
Map.Entry<K, V> firstEntry()返回最小键的 Entry
Map.Entry<K, V> lastEntry()返回最大键的 Entry
Map.Entry<K, V> pollFirstEntry()移除并返回最小键的 Entry
Map.Entry<K, V> pollLastEntry()移除并返回最大键的 Entry
SortedMap<K, V> subMap(K fromKey, K toKey)返回[fromKey, toKey) 范围的子 Map(视图,修改同步原 Map)
SortedMap<K, V> headMap(K toKey)返回<toKey 的子 Map
SortedMap<K, V> tailMap(K fromKey)返回≥fromKey 的子 Map
Comparator<? super K> comparator()返回排序用的 Comparator,自然排序返回 null
方法使用注意
  • put(key, value):若键未实现 Comparable 且无自定义 Comparator,抛 ClassCastException
  • 导航方法(如 ceilingKey)是 TreeMap 核心优势,适合范围查询场景。

4. Hashtable(古老线程安全)

核心特性
  • 底层:数组+链表;线程安全(方法加 synchronized);无序;不允许 null 键值;性能极低。
特有/重写方法
  • 所有方法均加 synchronized(如 public synchronized V put(K key, V value)),锁整个 Hashtable。
  • 重写 contains(Object value):等价于 containsValue(value)(历史遗留方法,不推荐使用)。
方法使用注意
  • put(null, value) 直接抛 NullPointerException,与 HashMap 差异核心。
  • 已被 ConcurrentHashMap 替代,仅兼容老代码。

5. ConcurrentHashMap(高并发线程安全)

核心特性
  • 底层:JDK1.8=数组+链表+红黑树+CAS+锁单个 Node;高并发安全;无序;不允许 null 键值;并发性能最优。
特有方法(原子操作/并发相关)
特有方法作用
V putIfAbsent(K key, V value)原子插入(核心并发方法):避免多线程重复插入,比 put 安全
boolean remove(Object key, Object value)原子条件删除:多线程下避免误删
boolean replace(K key, V oldValue, V newValue)原子条件替换
V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)原子懒加载插入(JDK8+),避免并发下重复计算
int mappingCount()返回键值对数量(比 size() 更准确,高并发下 size() 是近似值)
ConcurrentNavigableMap<K, V> subMap(...)仅 JDK1.8 支持可导航子 Map(分段锁版本无)
方法使用注意
  • keySet().iterator().remove() 方法(迭代器不支持删除,需用 remove(key))。
  • 所有原子方法(putIfAbsent、computeIfAbsent)是并发场景的核心,避免手动加锁。

6. WeakHashMap(弱引用键,自动回收)

核心特性
  • 底层:数组+链表;非线程安全;无序;键为弱引用,GC 自动回收无强引用的键;允许 null 键值。
特有/重写方法(无特有方法,核心是弱引用逻辑)
  • 重写 expungeStaleEntries():遍历并移除被 GC 回收的键对应的 Entry(put/get 时自动触发)。
方法使用注意
  • get(key) 会触发清理过期 Entry,因此遍历前建议先调用 size() 触发清理。
  • 避免值强引用键:若 value -> key 形成强引用,键无法被 GC 回收,导致内存泄漏。

7. IdentityHashMap(引用相等判断)

核心特性
  • 底层:数组+链表;非线程安全;无序;键相等判断用 ==(引用)而非 equals();允许 null 键值。
特有/重写方法(核心是重写键相等逻辑)
  • 重写 hash(Object key):直接用 System.identityHashCode(key)(基于对象引用地址)。
  • 重写 eq(Object k1, Object k2):返回 k1 == k2(而非 k1.equals(k2))。
方法使用示例
IdentityHashMap<String, Integer> map = new IdentityHashMap<>();
String s1 = new String("a");
String s2 = new String("a");
map.put(s1, 1);
map.put(s2, 2);
System.out.println(map.size()); // 2(s1和s2引用不同,视为不同键)

8. EnumMap(枚举键,极致性能)

核心特性
  • 底层:数组(基于枚举 ordinal() 索引);非线程安全;按枚举声明顺序;不允许 null 键;O(1) 性能。
特有方法/构造方法
特有方法/构造方法作用
EnumMap(Class<K> keyType)构造方法:必须指定枚举类(确定数组长度)
EnumMap(EnumMap<K, ? extends V> m)复制另一个 EnumMap 的键值对
EnumMap(Map<K, ? extends V> m)从普通 Map 复制(仅当键为枚举时)
Set<K> keySet()返回按枚举声明顺序的键 Set(数组遍历,效率极高)
方法使用注意
  • put(key, value):key 必须是指定枚举类的实例,否则抛 NullPointerException/ClassCastException
  • 遍历 values() 直接按数组索引遍历,性能远高于 HashMap。

三、全维度对比表(特性+方法核心差异)

特性/方法HashMapLinkedHashMapTreeMapHashtableConcurrentHashMapWeakHashMapIdentityHashMapEnumMap
核心特性(复用)通用、高性能、无序插入/访问有序按键排序、导航方法线程安全(锁全表)高并发、原子方法弱引用键、自动回收引用相等判断枚举键、极致性能
特有核心方法removeEldestEntry、accessOrder构造firstKey/ceilingKey等导航方法contains(等价containsValue)putIfAbsent、mappingCountexpungeStaleEntries(隐式)基于==的hash/eq枚举专属构造方法
线程安全方法所有方法synchronizedCAS+锁Node、原子方法
null 处理(方法)put(null, v) 允许同HashMap自然排序put(null)抛异常put(null)抛异常put(null)抛异常同HashMap同HashMapput(null)抛异常
遍历性能高(entrySet)更高(双向链表)中(红黑树遍历)低(同步+链表)高(分段锁/Node锁)同HashMap同HashMap极高(数组遍历)
原子操作方法无(JDK8+ compute 非原子)同HashMap同HashMap有(synchronized)丰富(putIfAbsent等)同HashMap同HashMap

四、方法使用关键注意事项

  1. 线程安全方法选择

    • 多线程写操作:优先用 ConcurrentHashMap 的 putIfAbsent/computeIfAbsent,而非 Collections.synchronizedMap+普通 put。
    • 避免在 ConcurrentHashMap 中使用 forEach 时修改元素(迭代器弱一致性,不会抛 ConcurrentModificationException)。
  2. 有序遍历方法

    • 插入顺序:LinkedHashMap(默认)的 entrySet 遍历。
    • 键排序:TreeMap 的 navigableKeySetsubMap 范围遍历。
    • 枚举顺序:EnumMap 的 keySet 直接遍历(按枚举声明顺序)。
  3. 性能优化方法

    • HashMap/LinkedHashMap 初始化时指定容量(new HashMap(100)),避免扩容开销。
    • 避免用 containsValue(全量遍历),可维护额外 Set 存储值实现快速查询。
    • EnumMap 替代 HashMap(键为枚举时),方法调用性能提升 50%+。
  4. 内存安全方法

    • WeakHashMap 中避免值引用键:可将值改为弱引用,或用 WeakReference 包装键。
    • IdentityHashMap 仅用于“对象引用唯一”场景,避免误判(如 String 常量池对象)。

五、特性+方法 综合选型建议

场景需求首选 Map + 核心方法
单线程、高性能、无序HashMap + put/get/entrySet 遍历
单线程、插入/访问顺序、LRU缓存LinkedHashMap + 重写 removeEldestEntry + accessOrder=true
单线程、按键排序、范围查询TreeMap + ceilingKey/floorKey/subMap
多线程、高并发、原子操作ConcurrentHashMap + putIfAbsent/computeIfAbsent
缓存、自动清理无引用键WeakHashMap + get/put(自动触发 expungeStaleEntries)
区分对象引用(== 判断)IdentityHashMap + put/get(基于引用哈希)
键为枚举、极致性能EnumMap + 构造指定枚举类 + keySet 遍历
老项目兼容Hashtable(替换为 ConcurrentHashMap)
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐