在Java中,Map 和 Set 都是 java.util 包中的核心集合接口,但它们在设计目的、存储结构和应用场景上有本质区别。以下是详细对比:
1. 核心概念
| 特性 | Map(映射) | Set(集合) |
|---|---|---|
| 存储单元 | 键值对(Key-Value Pair) | 单个元素(Element) |
| 唯一性约束 | Key 唯一(Value 可重复) | 元素整体唯一(无重复值) |
| 典型实现 | HashMap, TreeMap, LinkedHashMap | HashSet, TreeSet, LinkedHashSet |
2. 数据结构差异
Map
-
存储 键值对(
Entry<K, V>),通过 Key 快速检索 Value。 -
Key 是唯一标识:两个 Key 的
equals()比较必须为false。 -
Value 可重复:不同 Key 可指向相同的 Value。
-
内部实现:
-
HashMap:哈希表 + 链表/红黑树(无序)。 -
TreeMap:红黑树(Key 按自然顺序或比较器排序)。 -
LinkedHashMap:哈希表 + 双向链表(保留插入顺序)。
-
Set
-
存储 独立元素(无关联值)。
-
元素整体唯一:通过
equals()和hashCode()保证唯一性。 -
内部实现:
-
Set本质是Map的封装(如HashSet内部用HashMap实现)。 -
HashSet:元素作为HashMap的 Key(Value 用虚拟对象填充)。 -
TreeSet:元素作为TreeMap的 Key(自动排序)。
-
3. 核心方法对比
| 操作 | Map 方法 | Set 方法 |
|---|---|---|
| 添加元素 | put(K key, V value) | add(E element) |
| 删除元素 | remove(K key) | remove(Object o) |
| 检查存在 | containsKey(K key) | contains(Object o) |
containsValue(V value) | ||
| 获取元素 | get(K key) → 返回 Value | 无直接获取方法(需迭代遍历) |
| 获取大小 | size() | size() |
| 遍历方式 | 迭代 keySet(), values(), 或 entrySet() | 直接迭代元素 |
4. 应用场景
| 场景 | 推荐使用 | 原因 |
|---|---|---|
| 存储员工ID与姓名映射 | Map | Key(ID)唯一,需通过ID快速查找姓名(Value) |
| 存储不重复的用户名集合 | Set | 用户名需唯一,无需关联额外值 |
| 统计单词出现频率 | Map | Key=单词,Value=频率(Key唯一,Value可重复) |
| 过滤重复数据(如去重) | Set | 自动排除重复元素 |
| 需要排序的键值对(如字典) | TreeMap | Key按顺序排列 |
| 保留元素插入顺序的集合 | LinkedHashSet | 按添加顺序迭代元素 |
5. 底层联系
-
Set基于Map实现:java
复制
下载
// HashSet 源码(简化) public class HashSet<E> { private transient HashMap<E, Object> map; private static final Object PRESENT = new Object(); // 虚拟值 public boolean add(E e) { return map.put(e, PRESENT) == null; // 元素作为Map的Key } }-
Set的元素实际是Map的 Key,Value 用固定虚拟对象占位。 -
因此
Set的性能和特性由其底层Map实现决定(如HashSet≈HashMap)。
-
6. 示例代码
Map 示例
java
复制
下载
Map<Integer, String> map = new HashMap<>();
map.put(1, "Alice"); // Key=1, Value="Alice"
map.put(2, "Bob");
map.put(3, "Alice"); // Value可重复
System.out.println(map.get(2)); // 输出: "Bob"
System.out.println(map.containsKey(1)); // true
System.out.println(map.containsValue("Bob")); // true
Set 示例
java
复制
下载
Set<String> set = new HashSet<>();
set.add("Apple");
set.add("Banana");
set.add("Apple"); // 重复元素被忽略
System.out.println(set.size()); // 输出: 2
System.out.println(set.contains("Banana")); // true
7. 关键总结
| 维度 | Map | Set |
|---|---|---|
| 设计目的 | 通过 Key 管理关联的 Value | 存储唯一元素集合 |
| 存储结构 | 键值对(Key-Value) | 独立元素(无关联值) |
| 元素唯一性 | Key 唯一,Value 可重复 | 元素整体唯一 |
| 数据关联性 | 强关联(Key→Value) | 无关联 |
| 查询效率 | 通过 Key 直接访问(O(1) 平均) | 需遍历或哈希查找(O(1) 平均) |
| 典型用途 | 字典、缓存、键值存储 | 去重、集合运算(并集/交集) |
选择建议:
-
需存储 关联数据 → 选
Map -
只需 唯一元素集合 → 选
Set

1273

被折叠的 条评论
为什么被折叠?



