Map和Set
- [两种数据模型:Key 与 Key-Value](#两种数据模型:Key 与 Key-Value)
- [Map 详解:键值对的映射容器](#Map 详解:键值对的映射容器)
-
- [Map 的概念](#Map 的概念)
- [Map.Entry<K, V> ⭐](#Map.Entry<K, V> ⭐)
- [Map 常用 API](#Map 常用 API)
- Map的特点
- [HashMap vs TreeMap](#HashMap vs TreeMap)
- [Set 详解:唯一元素的集合](#Set 详解:唯一元素的集合)
-
- [Set 的概念](#Set 的概念)
- [Set 常用 API](#Set 常用 API)
- [Set 的特点](#Set 的特点)
- [HashSet vs TreeSet](#HashSet vs TreeSet)
两种数据模型:Key 与 Key-Value

-
纯 Key 模型 :只存储关键字,用于判断"某个元素是否存在"。典型场景包括:判断单词是否在词典中、检查用户名是否已被注册。
-
Key-Value 模型:不仅存储关键字,还关联一个对应的值。典型场景包括:根据学号查学生信息、统计单词出现次数。
简单来说:Set 对应纯 Key 模型,Map 对应 Key-Value 模型 。在 Java 集合框架中,两者都是接口,需要通过具体实现类来使用 :
- Map 实现类:HashMap、TreeMap(均实现 Map 接口)
- Set 实现类:HashSet、TreeSet(均实现 Set 接口)
Map 详解:键值对的映射容器
Map 的概念
在深入 HashMap 和 TreeMap 之前, 需要先明确 Map 接口的核心定义与约束 :
- Map 是一个接口类,它没有继承自 Collection 接口,这与 List、Set 不同。
- Map 中存储的是
<K, V>结构的键值对,并且 Key 一定是唯一的,不能重复 。当使用put方法放入相同的 key 时,新的 value 会覆盖旧的 value。
Map.Entry<K, V> ⭐
Map.Entry<K, V> 是 Map 内部实现的用来存放 <key, value> 键值对映射关系的内部类 。当遍历 Map 时,拿到的就是一个个 Entry 对象。

该内部类主要提供了以下方法:
| 方法 | 解释 |
|---|---|
K getKey() |
返回 entry 中的 key |
V getValue() |
返回 entry 中的 value |
V setValue(V value) |
将键值对中的 value 替换为指定 value |
注意 :
Map.Entry<K, V>并没有提供设置 Key 的方法。这意味着 Map 中键值对的 Key 不能直接修改,如果要修改 Key,只能先将该 key 对应的映射删除,然后再插入新的 key-value 对。
Map 常用 API
以下是 Map 接口中最核心的方法,无论使用 HashMap 还是 TreeMap,这些 API 都是通用的:
| 方法 | 解释 |
|---|---|
V get(Object key) |
返回 key 对应的 value,若 key 不存在则返回 null |
V getOrDefault(Object key, V defaultValue) |
返回 key 对应的 value,若 key 不存在则返回默认值 defaultValue |
V put(K key, V value) |
设置 key 对应的 value,若 key 已存在则覆盖并返回旧值 |
V remove(Object key) |
删除 key 对应的映射关系,返回被删除的 value |
Set<K> keySet() |
返回所有 key 的不重复集合(因为 key 唯一) |
Collection<V> values() |
返回所有 value 的可重复集合(value 可能重复) |
Set<Map.Entry<K, V>> entrySet() |
返回所有的 key-value 映射关系 |
boolean containsKey(Object key) |
判断是否包含指定的 key |
boolean containsValue(Object value) |
判断是否包含指定的 value |
Map的特点
-
Map 不能直接实例化:Map 是一个接口,必须通过其实现类(如 TreeMap 或 HashMap)来实例化对象。
-
Map下的类不能使用迭代器进行遍历。
-
Key 唯一,Value 可重复:这是 Map 最核心的特性。
-
关于 null 值的支持差异 :
- TreeMap :插入键值对时,Key 不能为空 (会抛出
NullPointerException),Value 可以为空。 - HashMap :Key 和 Value 都可以为空。
- TreeMap :插入键值对时,Key 不能为空 (会抛出
-
Key 的分离与访问:Map 中的 Key 可以全部分离出来,存储到 Set 中进行访问(因为 Key 不能重复,正好符合 Set 的特性)。
-
Value 的分离与访问:Map 中的 value 可以全部分离出来,存储在 Collection 的任何一个子集合中(因为 value 可能有重复)。
-
Key 不可直接修改:Map 中键值对的 Key 不能直接修改,value 可以修改。如果要修改 Key,只能先将该 key 删除,然后再重新插入新的键值对。
HashMap vs TreeMap
| 特性 | HashMap | TreeMap |
|---|---|---|
| 底层结构 | 哈希表(数组+链表+红黑树) | 红黑树 |
| 时间复杂度 | O(1) | O(log n) |
| 元素顺序 | 无序 | 按键的自然顺序或比较器排序 |
| null 支持 | key 和 value 均可为 null | key 不能为 null,value 可以为 null |
| 比较要求 | 自定义对象需重写 hashCode() 和 equals() | key 必须实现 Comparable 或传入 Comparator |
- 不关心顺序、追求极致性能 → 选 HashMap
- 需要按键有序遍历 → 选 TreeMap
Set 详解:唯一元素的集合
Set 的概念
在深入 HashSet 和 TreeSet 之前,需要先明确 Set 接口的核心定义与约束:
- Set 是继承自 Collection 的一个接口类,这意味着它拥有 Collection 的所有方法,同时有自己的特性约束。
- Set 的核心特征是元素不可重复 ,向 Set 中添加已存在的元素会被直接忽略 。
Set 常用 API
以下是 Set 接口中最核心的方法,无论使用 HashSet 还是 TreeSet,这些 API 都是通用的:
| 方法 | 解释 |
|---|---|
boolean add(E e) |
添加元素,但重复元素不会被添加成功(返回 false) |
void clear() |
清空集合中的所有元素 |
boolean contains(Object o) |
判断元素 o 是否在集合中 |
Iterator<E> iterator() |
返回迭代器,用于遍历集合 |
boolean remove(Object o) |
删除集合中的元素 o,删除成功返回 true |
int size() |
返回 Set 中元素的个数 |
boolean isEmpty() |
检测 Set 是否为空,空返回 true,否则返回 false |
Object[] toArray() |
将 Set 中的元素转换为数组返回 |
boolean containsAll(Collection<?> c) |
判断集合 c 中的元素是否在 Set 中全部存在 |
boolean addAll(Collection<? extends E> c) |
将集合 c 中的元素添加到 Set 中,可以达到去重的效果 |
Set 的特点
- Set 中只存储了 Key,并且要求 Key 一定要唯一,不能重复
- Set 最大的功能就是对集合中的元素进行去重
- Set 中的 Key 不能修改,如果要修改,只能先将原来的删除掉,然后再重新插入
HashSet vs TreeSet
| 特性 | HashSet | TreeSet |
|---|---|---|
| 底层结构 | HashMap(只用 key,value 为固定常量) | TreeMap(只用 key) |
| 时间复杂度 | O(1) | O(log n) |
| 元素顺序 | 无序 | 有序(自然顺序或比较器) |
| null 支持 | 允许一个 null 元素 | 不允许 null(会抛 NullPointerException) |
| 比较要求 | 需重写 hashCode() 和 equals() | 元素必须实现 Comparable 或传入 Comparator |