我们将从以下几个方面来详细介绍 HashMap 的方法:

- 核心方法:最常用、最基本的方法。
- 批量操作方法:用于处理多个键值对。
- 视图方法:获取
HashMap的不同“视图”。 - 辅助方法:获取容量、大小等信息。
- 哈希相关方法:理解其内部工作原理的关键。
- Java 8+ 新增方法:利用 Lambda 表达式进行更简洁的编程。
核心方法
这些方法是日常开发中使用频率最高的。
V put(K key, V value)
-
功能:将指定的键值对存入此映射中。
-
返回值:
- 如果之前该键已经存在,则返回之前与该键关联的旧值。
- 如果键不存在,则返回
null。
-
示例:
(图片来源网络,侵删)Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); // 返回 null scores.put("Bob", 88); // 返回 null Integer oldScore = scores.put("Alice", 98); // 返回旧的值 95 System.out.println("Alice's new score: " + scores.get("Alice")); // 输出 98 System.out.println("Old score was: " + oldScore); // 输出 95
V get(Object key)
-
功能:返回指定键所映射的值。
-
返回值:
- 如果找到键,返回对应的值。
- 如果键不存在,返回
null。 - 注意:
value本身就是null,get(key)返回null无法区分是键不存在还是值是null,此时需要用containsKey(key)来判断。
-
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); System.out.println("Alice's score: " + scores.get("Alice")); // 输出 95 System.out.println("Charlie's score: " + scores.get("Charlie")); // 输出 null
V remove(Object key)
-
功能:从此映射中移除指定键的映射关系(如果存在)。
(图片来源网络,侵删) -
返回值:
- 如果键存在,返回被移除的值。
- 如果键不存在,返回
null。
-
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); Integer removedScore = scores.remove("Alice"); // 返回 95 System.out.println("Removed score: " + removedScore); // 输出 95 System.out.println("Is Alice still in the map? " + scores.containsKey("Alice")); // 输出 false
boolean containsKey(Object key)
-
功能:如果此映射包含指定键的映射关系,则返回
true。 -
用途:用于安全地检查一个键是否存在,避免因
get()返回null而产生歧义。 -
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); if (scores.containsKey("Alice")) { System.out.println("Alice is in the map."); }
boolean containsValue(Object value)
- 功能:如果此映射将一个或多个键映射到指定值,则返回
true。 - 注意:此方法的性能通常比
containsKey()差,因为它需要遍历所有值。
boolean isEmpty()
- 功能:如果此映射不包含键值映射关系,则返回
true。
int size()
- 功能:返回此映射中的键值映射关系数。
批量操作方法
这些方法用于一次性执行多个操作,非常高效。
void putAll(Map<? extends K, ? extends V> m)
-
功能:将指定映射
m中的所有映射关系复制到此映射中。 -
示例:
Map<String, Integer> map1 = new HashMap<>(); map1.put("A", 1); Map<String, Integer> map2 = new HashMap<>(); map2.put("B", 2); map2.put("C", 3); map1.putAll(map2); // map1 现在包含 A, B, C
void clear()
- 功能:从此映射中移除所有映射关系,此调用返回后,映射将为空。
视图方法
视图方法是 HashMap 功能强大的体现,它们提供了对 HashMap 内部数据结构的访问,并且是动态的,即当 HashMap 发生变化时,视图也会随之变化。
Set<K> keySet()
-
功能:返回此映射中包含的键的
Set视图。 -
用途:可以遍历所有的键,或者通过该
Set来删除键。 -
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); scores.put("Bob", 88); Set<String> names = scores.keySet(); for (String name : names) { System.out.println(name); // 输出 Alice, Bob (顺序不确定) } // 通过视图删除 names.remove("Alice"); // 这会从原始的 HashMap 中移除 "Alice"
Collection<V> values()
-
功能:返回此映射中包含的值的
Collection视图。 -
用途:可以遍历所有的值。
-
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); scores.put("Bob", 88); Collection<Integer> allScores = scores.values(); for (Integer score : allScores) { System.out.println(score); // 输出 95, 88 (顺序不确定) }
Set<Map.Entry<K, V>> entrySet()
-
功能:返回此映射中包含的键值映射关系的
Set视图。Map.Entry是一个表示单个键值对的接口。 -
用途:这是最强大的视图,因为它允许你同时访问键和值,推荐在需要遍历整个映射时使用
entrySet(),因为它比先遍历keySet()再通过get()获取值的效率更高。 -
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); scores.put("Bob", 88); for (Map.Entry<String, Integer> entry : scores.entrySet()) { String name = entry.getKey(); Integer score = entry.getValue(); System.out.println(name + ": " + score); }
辅助方法
Object clone()
- 功能:创建此
HashMap实例的浅拷贝。 - 注意:它创建了一个新的
HashMap对象,并复制了所有键值对,键和值对象本身没有被复制,新映射和旧映射共享这些对象,这是一个浅拷贝。
哈希相关方法
理解这些方法有助于理解 HashMap 的工作原理。
int hashCode()
- 功能:返回此映射的哈希码值。
HashMap内部会维护一个哈希码,用于快速判断两个HashMap是否可能相等。 - 实现:哈希码是其所有条目的哈希码的异或 (
^) 总和。
boolean equals(Object o)
- 功能:将指定对象与此映射进行比较,以判断它们是否相等。
- 规则:两个
HashMap相等,当且仅当它们包含相同的键值对,且两个键k1和k2满足(k1==null ? k2==null : k1.equals(k2)),两个值v1和v2也满足相同的条件。
Java 8+ 新增方法
Java 8 引入的 Lambda 表达式和 Stream API,让 HashMap 的操作更加简洁和强大。
V getOrDefault(Object key, V defaultValue)
-
功能:返回指定键映射到的值,如果该映射不包含该键的映射关系,则返回
defaultValue。 -
优点:比
get()+containsKey()的组合更简洁。 -
示例:
Map<String, Integer> scores = new HashMap<>(); // scores.put("Alice", 95); // 假设 Alice 不存在 int score = scores.getOrDefault("Alice", 0); // 如果不存在,返回默认值 0 System.out.println("Score: " + score); // 输出 0
V putIfAbsent(K key, V value)
-
功能:如果指定的键尚未映射到值,则将其映射到给定的值。
-
返回值:返回与
key关联的先前值,key没有映射关系,则返回null。 -
用途:线程安全的原子操作(在单线程环境下可以优雅地避免重复计算或覆盖)。
-
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); // Alice 不存在,才设置值为 100 scores.putIfAbsent("Alice", 100); // Alice 已存在,此操作无效,返回 95 scores.putIfAbsent("Bob", 88); // Bob 不存在,设置成功,返回 null System.out.println(scores); // 输出 {Alice=95, Bob=88}
boolean remove(Object key, Object value)
-
功能:仅当指定键当前映射到指定值时,才移除该条目。
-
返回值:如果移除成功,返回
true;否则返回false。 -
用途:精确删除,避免误删。
-
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); boolean removed1 = scores.remove("Alice", 100); // key存在但value不匹配,返回 false boolean removed2 = scores.remove("Alice", 95); // key和value都匹配,返回 true System.out.println(removed1); // false System.out.println(removed2); // true System.out.println(scores.isEmpty()); // true
void replace(K key, V oldValue, V newValue)
-
功能:仅当指定键当前映射到指定值时,才替换该条目。
-
返回值:无 (void)。
-
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); scores.replace("Alice", 95, 100); // 替换成功 scores.replace("Bob", 88, 90); // Bob不存在,不执行任何操作 System.out.println(scores); // 输出 {Alice=100}
V replace(K key, V value)
-
功能:仅当指定键当前映射到某个值时,才替换该条目。
-
返回值:返回与
key关联的先前值,key没有映射关系,则返回null。 -
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); Integer oldVal = scores.replace("Alice", 100); // 返回 95 Integer newVal = scores.replace("Bob", 88); // Bob不存在,返回 null System.out.println(oldVal); // 95 System.out.println(newVal); // null
void forEach(BiConsumer<? super K, ? super V> action)
-
功能:对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。
-
优点:代码更简洁,无需手动迭代。
-
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); scores.put("Bob", 88); scores.forEach((name, score) -> System.out.println(name + " scored " + score));
void replaceAll(BiFunction<? super K, ? super V, ? extends V> function)
-
功能:将对此映射中的每个条目替换为对该条目调用给定函数的结果。
-
用途:批量更新所有值。
-
示例:
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 95); scores.put("Bob", 88); // 将所有分数加 5 scores.replaceAll((name, oldScore) -> oldScore + 5); System.out.println(scores); // 输出 {Alice=100, Bob=93}
V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)
-
功能:如果指定的键尚未与值关联或与
null关联,则将其与给定的非null值关联,否则,用给定的重新映射函数对该键的当前值及其给定值进行计算,并用结果替换该值。 -
用途:非常强大,可以优雅地处理值的合并逻辑,例如列表的累加、计数等。
-
示例:
Map<String, List<String>> userRoles = new HashMap<>(); // 如果用户不存在,创建一个新列表;如果存在,将新角色添加到现有列表中 userRoles.merge("Alice", Arrays.asList("ADMIN"), (oldList, newRoleList) -> { oldList.addAll(newRoleList); return oldList; }); userRoles.merge("Alice", Arrays.asList("USER"), (oldList, newRoleList) -> { oldList.addAll(newRoleList); return oldList; }); System.out.println(userRoles.get("Alice")); // 输出 [ADMIN, USER]
V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
-
功能:尝试计算指定键及其当前映射的映射关系(如果有的话)。
-
用途:根据键和旧值计算一个新值,可以用于添加、更新或删除条目。
remappingFunction返回null,则该条目将被移除。 -
示例:
Map<String, Integer> counts = new HashMap<>(); // key 不存在,oldValue 为 null counts.compute("apple", (k, oldVal) -> oldVal == null ? 1 : oldVal + 1); counts.compute("apple", (k, oldVal) -> oldVal + 1); // 再次计算 System.out.println(counts); // 输出 {apple=2}
V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
-
功能:如果指定的键尚未与值关联或与
null关联,则尝试使用给定的映射函数计算其值,并将其输入到此映射中,除非null。 -
用途:延迟初始化或计算一个值,避免不必要的计算。
-
示例:
Map<String, Integer> counts = new HashMap<>(); // 只有当 "banana" 不存在时,才会执行 lambda 表达式 counts.computeIfAbsent("banana", k -> k.length()); // k.length() 返回 6 System.out.println(counts); // 输出 {banana=6}
V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
-
功能:如果指定键的当前映射值不为
null,则尝试在给定键及其当前映射值的情况下运行给定的重新映射函数,除非该值为null。 -
用途:仅在键存在且值不为
null时才进行计算。 -
示例:
Map<String, Integer> counts = new HashMap<>(); counts.put("cherry", 5); // 只有当 "cherry" 存在且值不为 null 时,才会执行 lambda counts.computeIfPresent("cherry", (k, oldVal) -> oldVal * 2); counts.computeIfPresent("mango", (k, oldVal) -> oldVal * 2); // mango 不存在,不执行 System.out.println(counts); // 输出 {cherry=10}
| 方法类别 | 核心方法 | 描述 |
|---|---|---|
| 基本操作 | put(), get(), remove() |
添加、获取、删除单个键值对。 |
| 查询 | containsKey(), containsValue(), isEmpty(), size() |
检查映射内容。 |
| 批量操作 | putAll(), clear() |
复制或清空整个映射。 |
| 视图 | keySet(), values(), entrySet() |
提供对键、值、键值对的动态访问视图。 |
| Java 8+ | getOrDefault(), putIfAbsent(), remove(), replace() |
原子操作,避免竞态条件。 |
| Java 8+ | forEach(), replaceAll(), merge(), compute() |
函数式编程,简化代码,实现复杂逻辑。 |
掌握这些方法,特别是 Java 8 引入的函数式方法,将极大地提高你使用 HashMap 的效率和代码的简洁性。
