Menu

Java HashMap:put、get、遍历与常用模式

如何用 Java 的 HashMap 做键值查找:put、get、getOrDefault、containsKey、遍历条目,以及最常用的几种模式。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

Map 存储键值对

HashMap(来自 java.util)存储的是对应关系:每个键映射到一个值,你可以按键查找值,时间大致是常数级。可以把它想成一本词典:单词是键,释义是值。

两个类型参数是 <KeyType, ValueType>。这里键是 String,值是 Integer。和 ArrayList 一样,通常把变量声明为 Map 接口类型,再构造一个 HashMap。

put、get 与覆盖

有两点要牢记:

  • 键是唯一的。对已存在的键调用 put 会替换它的值,并返回旧值。
  • 对不存在的键调用 get 会返回 null,而不是报错。把这个 null 自动拆箱成 int 会抛出 NullPointerException,这是常见的 bug 来源。

用 getOrDefault 避开 null 陷阱

与其每次都检查 null,不如直接要一个默认值:

这是处理“可能存在”的查找最干净的方式,它也直接引出了 HashMap 最有名的用法。

统计出现次数

统计每个元素出现了多少次,是 HashMap 的教科书式任务:

map.put(key, map.getOrDefault(key, 0) + 1) 这个模式的意思是“取出当前计数(没有就是零),加一,再存回去”。更简洁的等价写法是 counts.merge(word, 1, Integer::sum)。

检查与删除

putIfAbsent(key, value) 只在键不存在时才写入,适合用来做延迟初始化。

遍历 HashMap

最常见的循环是遍历 entrySet(),同时拿到每个键和值:

如果只需要键,或者只需要值:

你也可以把 forEach 和 lambda 搭配使用:ages.forEach((name, age) -> System.out.println(name + ": " + age));。

HashMap 不保证顺序

HashMap 对遍历顺序不做任何保证:顺序取决于哈希的结果,而且每次运行都可能不同。如果你需要可预测的顺序:

  • LinkedHashMap 保留插入顺序。
  • TreeMap 让键按自然顺序(或你提供的 Comparator)排序。

三者都实现了 Map 接口,所以切换只需改一行构造函数。

键必须可哈希

HashMap 通过对键做哈希来查找条目,所以键的 hashCode() 和 equals() 必须保持一致。String 和 Integer 等内置类型已经正确实现了这一点。如果你用自己的类作为键,就要同时重写 equals 和 hashCode,否则两个在含义上“相等”的对象会落进不同的桶里,查找会莫名其妙地失败。

下一篇:HashSet

HashMap 回答的是“这个键下面存的是什么值?”。如果你只关心某个东西在不在,也就是一组没有附带数据的唯一值,那么要用的工具是 HashSet,下一篇就讲它。

常见问题

Java 中如何创建 HashMap?

用两个类型参数(键的类型和值的类型)声明它,然后调用构造函数:Map<String, Integer> ages = new HashMap<>();。接着用 ages.put("Ada", 36); 添加条目,用 ages.get("Ada"); 读取。需要导入 java.util.HashMap 和 java.util.Map。

Java 中如何遍历 HashMap?

用 for-each 循环遍历 map.entrySet(),就能同时拿到每个键和值:for (Map.Entry<String, Integer> e : map.entrySet()) { ... },再读取 e.getKey() 和 e.getValue()。也可以遍历 map.keySet() 只取键,或遍历 map.values() 只取值。注意 HashMap 不保留插入顺序。

get 和 getOrDefault 有什么区别?

get(key) 返回键对应的值,如果键不存在则返回 null,直接使用这个结果可能导致 NullPointerException。getOrDefault(key, fallback) 在值存在时返回值,否则返回你传入的默认值,这样就省掉了 null 检查。它在计数时特别方便:counts.put(c, counts.getOrDefault(c, 0) + 1)。

Coddy 编程语言插图

和 Coddy 一起学编程

开始