HashMap HashSet
1. 一眼区分
HashMap<K, V>:存的是key -> valueHashSet<E>:存的是单个元素EMap用putSet用add,没有put
核心区别
HashMap:key不能重复,value可以重复HashSet:元素不能重复- 两者都属于哈希结构,查找平均时间复杂度通常是
O(1)
2. 常用 API
HashMap 常用方法
put(key, value):添加或更新get(key):按key取值getOrDefault(key, defaultValue):取值,取不到就返回默认值containsKey(key):判断key是否存在containsValue(value):判断value是否存在,能用但很少用remove(key):删除指定key
HashSet 常用方法
add(e):添加元素contains(o):判断元素是否存在remove(o):删除元素
Note
Set只有contains(Object o),没有containsKey()这种说法。
3. 高频写法
计数
map.put(x, map.getOrDefault(x, 0) + 1);这句是刷题里最常见的 HashMap 用法之一:
- 如果
x已经存在,就在原值基础上+1 - 如果
x不存在,就先用默认值0
本质上就是一种“尝试更新”的写法,和 Math.max() 的思路很像。
判断是否出现过
if (set.contains(x)) {
// 出现过
} else {
set.add(x);
}遍历 Map
for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {
int key = entry.getKey();
int value = entry.getValue();
}相关题目:2._前k个高频元素
4. 为什么推荐 entrySet()
不推荐:keySet() + get()
for (String key : map.keySet()) {
String value = map.get(key);
}问题在于:
- 先拿到
key - 再通过
get(key)回去找一次value - 写起来可以,但不够直接
推荐:entrySet()
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
}优点:
- 一次就拿到一对
key-value - 语义更清楚
- 遍历场景下更常用
5. 怎么理解 Map.Entry
可以把 Map 想成一个装满“键值对包裹”的仓库:
Map:大仓库Entry:一个个打包好的键值对entrySet():把这些包裹组成一个集合
所以:
Map.Entry<K, V>是“一个键值对”的类型map.entrySet()是把所有键值对拿出来entry.getKey()/entry.getValue()是从当前这一个键值对里取值
记忆方式
keySet()=key的集合entrySet()=entry的集合
之所以叫 entrySet(),是因为返回值本身就是一个 Set。
6. Java 8 之后的简写
map.forEach((key, value) -> {
System.out.println("键:" + key + ",值:" + value);
});这种写法本质上还是在遍历键值对,只是把 Entry 的细节隐藏掉了。
7. 刷题时要记住的坑
遍历时不要直接修改 Map
如果一边遍历,一边直接增删 Map,可能会报:
ConcurrentModificationException这类场景通常要配合 Iterator 处理。
8. 最后速记
Map看的是keySet看的是元素本身Map常用:put、get、getOrDefault、containsKeySet常用:add、contains- 遍历
Map优先写entrySet()