核心概念
在深入方法之前,必须理解 HashMap 的两个核心概念:

- 键-值对:
HashMap存储的是Entry对象,每个Entry对象包含一个key和一个value。key必须是唯一的。 - 哈希冲突:不同的
key可能有相同的哈希值(hashCode()的结果)。HashMap通过“链地址法”或“红黑树”来解决冲突,在 Java 8 中,当链表长度超过 8 且数组长度超过 64 时,链表会转换为红黑树以提高查询效率。
构造方法
创建 HashMap 实例时,可以使用不同的构造方法。
| 方法签名 | 描述 |
|---|---|
HashMap() |
构造一个具有默认初始容量(16)和默认加载因子(0.75)的空 HashMap。 |
HashMap(int initialCapacity) |
构造一个具有指定初始容量和默认加载因子(0.75)的空 HashMap。 |
HashMap(int initialCapacity, float loadFactor) |
构造一个具有指定初始容量和加载因子的空 HashMap。 |
HashMap(Map<? extends K, ? extends V> m) |
构造一个与指定 Map 具有相同映射关系的新的 HashMap。 |
示例:
// 默认构造
Map<String, Integer> map1 = new HashMap<>();
// 指定初始容量
Map<String, Integer> map2 = new HashMap<>(32);
// 从另一个Map构造
Map<String, Integer> originalMap = new HashMap<>();
originalMap.put("A", 1);
Map<String, Integer> map3 = new HashMap<>(originalMap);
基本操作方法
这些是 HashMap 最常用、最核心的方法。
| 方法签名 | 描述 | 返回值 |
|---|---|---|
V put(K key, V value) |
将指定的键值对存入此映射。key 已经存在,则更新其对应的 value,并返回旧的 value。key 不存在,则返回 null。 |
V (旧的值) |
V get(Object key) |
返回指定 key 所映射的 value,如果映射中不包含该 key 的映射关系,则返回 null。 |
V (对应的值) |
V remove(Object key) |
如果存在,从此映射中移除指定 key 的映射关系(及其对应的 value),并返回被移除的 value。key 不存在,则返回 null。 |
V (被移除的值) |
boolean containsKey(Object key) |
如果此映射包含指定 key 的映射关系,则返回 true。 |
boolean |
boolean containsValue(Object value) |
如果此映射将一个或多个 key 映射到指定 value,则返回 true。 |
boolean |
boolean isEmpty() |
如果此映射不包含键值映射关系,则返回 true。 |
boolean |
int size() |
返回此映射中的键值映射关系数。 | int |
示例:

HashMap<String, Integer> scores = new HashMap<>();
// put
scores.put("Alice", 95);
scores.put("Bob", 88);
scores.put("Alice", 99); // 更新 Alice 的分数
System.out.println("After put: " + scores); // {Bob=88, Alice=99}
// get
Integer aliceScore = scores.get("Alice");
System.out.println("Alice's score: " + aliceScore); // 99
// containsKey
System.out.println("Contains 'Bob'? " + scores.containsKey("Bob")); // true
System.out.println("Contains 'Charlie'? " + scores.containsKey("Charlie")); // false
// remove
Integer removedScore = scores.remove("Bob");
System.out.println("Removed Bob's score: " + removedScore); // 88
System.out.println("After remove: " + scores); // {Alice=99}
// size, isEmpty
System.out.println("Size: " + scores.size()); // 1
System.out.println("Is empty? " + scores.isEmpty()); // false
批量操作方法
这些方法用于一次性操作整个映射。
| 方法签名 | 描述 | 返回值 |
|---|---|---|
void putAll(Map<? extends K, ? extends V> m) |
从指定映射中将所有映射关系复制到此映射中。 | void |
void clear() |
从此映射中移除所有映射关系,此调用返回后,映射将为空。 | void |
示例:
HashMap<String, Integer> map1 = new HashMap<>();
map1.put("A", 1);
map1.put("B", 2);
HashMap<String, Integer> map2 = new HashMap<>();
map2.put("C", 3);
map2.put("A", 4); // map1 中也有的 key
// putAll: 将 map2 的内容合并到 map1,key 冲突,map1 的值会被 map2 的值覆盖。
map1.putAll(map2);
System.out.println("After putAll: " + map1); // {A=4, B=2, C=3}
// clear
map1.clear();
System.out.println("After clear: " + map1); // {}
System.out.println("Is empty? " + map1.isEmpty()); // true
视图操作方法
这些方法返回 HashMap 内部数据的“视图”,对视图的修改会直接反映到原始的 HashMap 中,它们是遍历和操作 HashMap 的强大工具。
| 方法签名 | 描述 | 返回值 |
|---|---|---|
Set<K> keySet() |
返回此映射中包含的 key 的 Set 视图。 |
Set<K> |
Collection<V> values() |
返回此映射中包含的 value 的 Collection 视图。 |
Collection<V> |
Set<Map.Entry<K, V>> entrySet() |
返回此映射中包含的 Map.Entry 的 Set 视图,这是最常用的遍历方式。 |
Set<Map.Entry<K, V>> |
示例:

HashMap<String, Integer> scores = new HashMap<>();
scores.put("Alice", 95);
scores.put("Bob", 88);
scores.put("Charlie", 76);
// 1. keySet() - 遍历 key
System.out.println("--- Traversing Keys ---");
for (String name : scores.keySet()) {
System.out.println("Name: " + name);
}
// 2. values() - 遍历 value
System.out.println("\n--- Traversing Values ---");
for (Integer score : scores.values()) {
System.out.println("Score: " + score);
}
// 3. entrySet() - 遍历 key-value 对 (推荐方式)
System.out.println("\n--- Traversing Entries ---");
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
System.out.println("Name: " + entry.getKey() + ", Score: " + entry.getValue());
}
// 通过视图修改原 Map
Set<String> keys = scores.keySet();
keys.remove("Bob"); // 直接通过视图的 remove 方法修改原 Map
System.out.println("\nAfter removing 'Bob' via keySet view: " + scores); // {Charlie=76, Alice=95}
其他实用方法
| 方法签名 | 描述 | 返回值 |
|---|---|---|
boolean equals(Object o) |
比较此映射与指定对象是否相等。 | boolean |
int hashCode() |
返回此映射的哈希码值。 | int |
Object clone() |
返回此 HashMap 实例的浅表副本。 |
Object |
Java 8+ 新增方法
Java 8 为 HashMap 及其父接口 Map 引入了许多非常有用的方法,使其功能更强大。
| 方法签名 | 描述 | 返回值 |
|---|---|---|
V getOrDefault(Object key, V defaultValue) |
返回指定 key 对应的 value,key 不存在,则返回 defaultValue。 |
V |
V putIfAbsent(K key, V value) |
只有在 key 不存在时,才将指定的键值对存入此映射。 |
V (key 不存在,返回 null;如果存在,返回旧值) |
boolean remove(Object key, Object value) |
只有在 key 存在且其当前映射的 value 与给定的 value 相等时,才移除该条目。 |
boolean (是否移除成功) |
V replace(K key, V value) |
只有在 key 存在时,才替换其 value。 |
V (key 存在,返回旧值;否则返回 null) |
boolean replace(K key, V oldValue, V newValue) |
只有在 key 存在且其当前映射的 value 等于 oldValue 时,才将其替换为 newValue。 |
boolean (是否替换成功) |
void forEach(BiConsumer<? super K, ? super V> action) |
对此映射中的每个条目执行给定的操作,直到所有条目都被处理完毕或操作抛出异常。 | void |
void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) |
将此映射中的每个条目的值替换为对该条目调用给定函数的结果。 | void |
V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) |
key 对应的 value 为 null 或不存在,则使用给定的函数计算其 value 并存入映射。 |
V |
V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) |
key 对应的 value 不为 null,则使用给定的函数重新计算其 value。 |
V |
V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) |
使用给定的函数计算指定 key 的新 value。 |
V |
V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) |
key 不存在,则将其与给定的 value 关联。key 存在,则用给定的函数对其当前 value 和给定的 value 进行合并,并用结果替换旧 value。 |
V |
示例 (Java 8+):
HashMap<String, Integer> map = new HashMap<>();
// getOrDefault
System.out.println("getOrDefault 'David': " + map.getOrDefault("David", 0)); // 0
// putIfAbsent
map.putIfAbsent("Alice", 95);
map.putIfAbsent("Alice", 100); // 不会执行,因为 Alice 已存在
System.out.println("After putIfAbsent: " + map); // {Alice=95}
// replace
map.replace("Alice", 98);
System.out.println("After replace: " + map); // {Alice=98}
// replace with old value check
map.replace("Alice", 98, 99); // 会执行,因为旧值是98
map.replace("Alice", 100, 99); // 不会执行,因为旧值不是100
System.out.println("After conditional replace: " + map); // {Alice=99}
// remove with old value check
map.remove("Alice", 99); // 会执行,成功移除
map.remove("Alice", 95); // 不会执行,因为 Alice 已不存在
System.out.println("After conditional remove: " + map); // {}
// computeIfAbsent
map.computeIfAbsent("Bob", k -> 0); // Bob 不存在,则计算并设置其值为 0
map.computeIfAbsent("Bob", k -> 100); // Bob 已存在,此操作不执行
System.out.println("After computeIfAbsent: " + map); // {Bob=0}
// forEach
map.forEach((k, v) -> System.out.println("Key: " + k + ", Value: " + v));
// 输出:
// Key: Bob, Value: 0
// merge
map.merge("Bob", 5, Integer::sum); // Bob 存在,将 0 + 5 = 5 作为新值
map.merge("Charlie", 10, Integer::sum); // Charlie 不存在,直接设置为 10
System.out.println("After merge: " + map); // {Bob=5, Charlie=10}
遍历 HashMap 的几种方式
遍历是 HashMap 的核心操作,主要有以下四种方式:
使用 entrySet() 和 for-each 循环 (推荐)
这是最常用、最高效的方式,因为它通过迭代器直接访问 Map.Entry 对象,避免了多次调用 get() 方法。
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + " : " + value);
}
使用 keySet() 和 for-each 循环
这种方式先遍历 key,然后在循环体中通过 key 获取 value,如果只需要 key,这种方式很方便。
for (String key : map.keySet()) {
Integer value = map.get(key);
System.out.println(key + " : " + value);
}
使用 Iterator
entrySet(), keySet(), values() 都返回一个集合,可以使用迭代器进行遍历。
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
// 可以在遍历时安全地删除元素
if (entry.getValue() < 50) {
iterator.remove();
}
}
使用 Java 8 的 forEach 和 Lambda 表达式
代码简洁,函数式风格。
map.forEach((key, value) -> System.out.println(key + " : " + value));
| 功能类别 | 核心方法 |
|---|---|
| 基本操作 | put(), get(), remove(), containsKey(), size() |
| 批量操作 | putAll(), clear() |
| 视图操作 | keySet(), values(), entrySet() |
| Java 8+ 增强 | getOrDefault(), putIfAbsent(), replace(), remove(), computeIfAbsent(), merge(), forEach() |
掌握这些方法,特别是 entrySet() 遍历和 Java 8 引入的新方法,将极大地提高你使用 HashMap 的效率和代码质量。
