--- title: "00-Map总览" created: 2025-12-02 tags: - Java --- # Map > [!note] 定位说明 > 本篇是 Map 系列总览:Map 核心特性 + 四实现类对比 + 选型入门。深读动线:[[01-HashMap|HashMap]] → [[02-HashMap源码解析|HashMap 源码]] → [[03-LinkedHashMap|LinkedHashMap]](LRU)→ [[05-TreeMap|TreeMap]](排序,含 [[07-红黑树|红黑树]] 前置篇)。 ### **Map 核心特性** 1. **键值对存储** - 每个条目由 **键(Key)** 和 **值(Value)** 组成,键唯一(底层通过 `equals()` 和 `hashCode()` 保证),值可重复。 - 典型操作:`put(K key, V value)`(插入 / 更新)、`get(Object key)`(通过键取值)、`containsKey(Object key)`(判断键是否存在)。 2. **无序性与有序性** - **无序 Map**(如 `HashMap`):键值对的存储顺序与插入顺序无关,遍历时顺序不可预测。 - **有序 Map**(如 `LinkedHashMap`、`TreeMap`): - `LinkedHashMap` 按**插入顺序**或**访问顺序**维护条目顺序。 - `TreeMap` 按**键的自然排序**或**自定义比较器**排序(如字典序、数值大小)。 3. **线程安全性** - 核心实现类(`HashMap`、`LinkedHashMap`、`TreeMap`)**非线程安全**,多线程场景需使用 `ConcurrentHashMap` 或手动同步(如 `Collections.synchronizedMap()`)。 4. **null 支持** - `HashMap`、`LinkedHashMap`:允许 **1 个 null 键**和 **多个 null 值**(`TreeMap` 不允许null 键,`Hashtable` 不允许任何 null)。 ### **核心实现类概览** | **实现类** | **数据结构** | **顺序性** | **线程安全** | **null 键支持** | **典型场景** | | --- | --- | --- | --- | --- | --- | | [[2-Learning/04-Java/02-Java容器/04-Map系列/01-HashMap|HashMap]] | 哈希表(数组 + 链表 + 红黑树) | 无序 | 非安全 | 允许 | 快速键值对查询(如缓存、字典) | | [[2-Learning/04-Java/02-Java容器/04-Map系列/03-LinkedHashMap|LinkedHashMap]] | 哈希表 + 双向链表 | 插入 / 访问顺序 | 非安全 | 允许 | 有序存储、LRU 缓存 | | [[2-Learning/04-Java/02-Java容器/04-Map系列/05-TreeMap|TreeMap]] | 红黑树(自平衡二叉树) | 自然 / 定制排序 | 非安全 | 不允许 | 排序、范围查询(如字典序统计) | | [[2-Learning/04-Java/02-Java容器/00-容器总览|Hashtable(见总览)]] | 哈希表(数组 + 链表) | 无序 | 安全(同步) | 不允许 | 旧系统线程安全场景(极少使用) | ### **与 Set、Queue 的对比** | **接口 / 类** | **存储形式** | **核心特性** | **典型场景** | | --- | --- | --- | --- | | **Set** | 单一元素 | 元素唯一、无序 / 有序(取决于实现类) | 去重、唯一性校验 | | **Queue** | 线性元素(FIFO) | 先进先出、支持阻塞操作(如 `BlockingQueue`) | 任务队列、消息传递 | | **Map** | 键值对 | 快速映射、键唯一、值可重复 | 数据关联、配置管理、统计计数 | ### **快速入门建议** 1. **优先使用 HashMap**: 若无特殊顺序或线程安全需求,`HashMap` 是性能最优的选择,适用于高频的 `put`/`get` 操作(如用户信息存储、缓存系统)。 2. **需要有序性时**: - 按插入顺序:选 `LinkedHashMap`(如用户操作日志记录)。 - 按键排序:选 `TreeMap`(如学生成绩排名、按时间戳排序的事件数据)。 3. **线程安全场景**: - 高并发:使用 `ConcurrentHashMap`(JDK 8 优化后性能显著提升)。 - 低并发且需兼容旧代码:使用 `Hashtable`(不推荐,仅用于遗留系统)。 4. **避免误区**: - 不要用 `TreeMap` 替代 `HashMap` 做普通映射(排序开销会降低性能)。 - `LinkedHashMap` 的访问顺序模式需配合 `removeEldestEntry` 实现 LRU,否则无法自动淘汰旧元素。 通过理解 `Map` 的核心特性与实现类差异,可根据业务需求快速选择合适的数据结构,提升代码效率和可维护性。 ### 上手示例:遍历三式与计数套路 ```java Map score = new HashMap<>(); score.put("Alice", 92); score.put("Bob", 85); // 1. entrySet——键值都要,首选(一次遍历拿全) for (Map.Entry e : score.entrySet()) { System.out.println(e.getKey() + " = " + e.getValue()); } // 2. keySet——只要键,值用 get 补(两次查找,略慢) for (String name : score.keySet()) { System.out.println(name); } // 3. values——只要值 for (Integer s : score.values()) { System.out.println(s); } // 4. forEach(JDK 8+,写起来最短) score.forEach((name, s) -> System.out.println(name + ":" + s)); ``` > [!tip] 两个日常最高频的套路 > **词频统计**——别写 `if (map.containsKey(k)) map.put(k, map.get(k)+1)` 三行了: > ```java > `map.merge(word, 1, Integer::sum);` // 存在则加 1,不存在放 1 > map.putIfAbsent(word, 0); // 只在缺键时补默认值 > int def = map.getOrDefault("nobody", 0); // 取值给默认值,避免 null > ``` > 这三个方法(`merge` / `putIfAbsent` / `getOrDefault`)是 JDK 8 给 Map 的"日常三件套",刷题和业务代码里到处都是。 --- ⬅️ [[02-PriorityQueue|PriorityQueue]] 🏠 [[00-Java|00-Java]] ➡️ [[01-HashMap|HashMap]]