248. Java 集合 - 使用 Map 存储键值对

40 阅读3分钟

248. Java 集合 - 使用 Map 存储键值对


1. 🌟 引入:什么是 Map🗺️?

Java 中,Map 是集合框架(Collections Framework)提供的第二大核心结构,它实现了一种非常经典、基础的数据存储模型:哈希表(HashMap)结构

这个概念并不新颖,早在计算机科学发展的早期,哈希表就已被广泛应用,用来高效地管理内存内外的数据。


2. 🧩 什么是哈希表(HashMap)?

哈希表的本质是:存储键值对(Key-Value Pair

  • 键(Key:用来标识定位一个对象。
  • 值(Value:真正需要操作的数据对象。

✨ 一个简单的例子:

假设你正在开发一个发票管理系统,需要处理大量的发票(Invoice 类的实例)。

  • Value(值):每一张发票对象。
  • Key(键):发票号(Invoice Number),通常是一个唯一的字符串或数字

通过发票号(key),就可以快速找到对应的发票信息(value)。


3. 🧠 Map 的核心特性总结

特性说明
1️⃣ 存储键值对每一对键和值绑定在一起,组成一个**Entry**
2️⃣ 键通常是简单对象StringInteger
3️⃣ 值可以是任意复杂对象比如对象、集合、甚至另一个 Map
4️⃣ 键在 Map 中必须唯一不允许重复键(Key
5️⃣ 值可以重复不同键可以指向相同的值
6️⃣ 通过键可以快速检索对应的值时间复杂度接近 O(1)

4. 📚 Map 接口的继承体系

Map 体系结构非常清晰,类似于 Set 的继承关系:

  • Map
    • SortedMap:保持键值对按键的自然顺序排序。
    • NavigableMap:在 SortedMap 基础上,增加了更强大的导航方法(如查找小于/大于某个键的条目)。

5. 🛠️ Map 接口常用实现类

🟢 HashMap(最常用)

  • 无序存储(即插入顺序不保证)。
  • 快速检索。
  • 允许 null 键和多个 null 值。
Map<String, Invoice> invoiceMap = new HashMap<>();
invoiceMap.put("INV-001", new Invoice("INV-001", 1500));
Invoice invoice = invoiceMap.get("INV-001"); // 通过 key 获取值

🟡 LinkedHashMap(有序存储)

  • 保持插入顺序
  • HashMap 略慢(因为需要维护顺序)。
  • 适合对遍历顺序有要求的场景。
Map<String, String> map = new LinkedHashMap<>();
map.put("A", "Apple");
map.put("B", "Banana");
map.put("C", "Cherry");

System.out.println(map.keySet()); // 输出: [A, B, C]

🔴 IdentityHashMap(基于 == 比较)

  • 极少使用!
  • 比较键时,不是用 .equals(),而是直接用 ==
  • 只有在你明确知道自己需要基于内存地址比较时才使用。
IdentityHashMap<String, String> idMap = new IdentityHashMap<>();
idMap.put(new String("A"), "Apple");
idMap.put(new String("A"), "Another Apple");

System.out.println(idMap.size()); // 输出 2,因为两个 "A" 是不同的对象

6. 🎯 什么是 Multimap

有时候我们希望一个键对应多个值,这就是**Multimap**的概念。

⚡ Java Collections Framework 本身不直接支持 Multimap

但是可以通过**Map<K, List>**自己简单实现:

Map<String, List<String>> multiMap = new HashMap<>();

multiMap.computeIfAbsent("fruit", k -> new ArrayList<>()).add("Apple");
multiMap.computeIfAbsent("fruit", k -> new ArrayList<>()).add("Banana");
multiMap.computeIfAbsent("vegetable", k -> new ArrayList<>()).add("Carrot");

System.out.println(multiMap.get("fruit")); // 输出: [Apple, Banana]

✅ 这样就模拟出了一个键对应多个值的结构!


7. ⚡ 小结:使用 Map 的场景总结

应用场景适合的实现
快速存取、无顺序要求HashMap
需要保持插入顺序LinkedHashMap
希望键对象按自然顺序排序(如数字、字母)TreeMapSortedMap实现)
特殊情况下基于内存地址比较IdentityHashMap
一个键需要关联多个值Map<K, List<V>> 手动模拟

👀 互动问题

问题1:如果要保持元素插入顺序,使用哪种 Map 实现?

答案示例:使用 LinkedHashMap

问题2:在什么情况下可能需要 IdentityHashMap

答案示例:在需要通过对象引用(==)判断相等,而不是通过 .equals() 比较内容时。

问题3MultimapJava Collections 中直接支持吗?如果不支持,我们怎么实现?

答案示例:不直接支持,可以通过 Map<K, List<V>> 结构模拟实现。