引言:什么是Map?
Map(映射)存储键值对(key-value)数据,可以通过键(key)快速找到对应的值(value)。
Map类比
Map就像一本字典:
┌─────────────┬───────────┐
│ 键(Key) │ 值(Value) │
├─────────────┼───────────┤
│ "cat" │ "猫" │
│ "dog" │ "狗" │
│ "bird" │ "鸟" │
└─────────────┴───────────┘
通过"dog"这个键,可以快速找到"狗"这个值
Map的特点:
- 键唯一:每个键最多只能对应一个值
- 值可重复:不同的键可以对应相同的值
- 键值对:存储的是key-value键值对
Map的主要实现类
| 实现类 | 特点 | 适用场景 |
|---|---|---|
| HashMap | 基于哈希表,无序 | 最常用,需要快速查找 |
| LinkedHashMap | 基于哈希表+链表,保持插入顺序 | 需要保持顺序 |
| TreeMap | 基于红黑树,按key排序 | 需要按key排序 |
| Hashtable | 线程安全,已过时 | 不推荐使用 |
HashMap的使用
创建HashMap
import java.util.HashMap;
import java.util.Map;
// 创建HashMap(推荐写法)
Map map = new HashMap<>();
添加元素 - put()
Map scores = new HashMap<>();
// 添加键值对
scores.put("张三", 95);
scores.put("李四", 88);
scores.put("王五", 92);
// key相同时,value会被覆盖
scores.put("张三", 100); // 张三的成绩被更新为100
System.out.println(scores); // {李四=88, 王五=92, 张三=100}
访问元素 - get()
Map scores = new HashMap<>();
scores.put("张三", 95);
scores.put("李四", 88);
// 通过key获取value
System.out.println(scores.get("张三")); // 95
System.out.println(scores.get("王五")); // null(key不存在)
// 安全获取:使用getOrDefault()
System.out.println(scores.getOrDefault("王五", 0)); // 0(key不存在时返回默认值)
删除元素 - remove()
Map scores = new HashMap<>();
scores.put("张三", 95);
scores.put("李四", 88);
// 按key删除
scores.remove("李四");
System.out.println(scores); // {张三=95}
// 清空所有
scores.clear();
System.out.println(scores); // {}
修改元素 - put()
Map scores = new HashMap<>();
scores.put("张三", 95);
// 修改:使用put()方法,如果key存在则覆盖value
scores.put("张三", 100);
System.out.println(scores.get("张三")); // 100
判断方法
Map scores = new HashMap<>();
scores.put("张三", 95);
// 判断是否包含key
System.out.println(scores.containsKey("张三")); // true
System.out.println(scores.containsKey("李四")); // false
// 判断是否包含value
System.out.println(scores.containsValue(95)); // true
System.out.println(scores.containsValue(100)); // false
// 判断是否为空
System.out.println(scores.isEmpty()); // false
遍历Map的几种方式
方式1:遍历key
Map scores = new HashMap<>();
scores.put("张三", 95);
scores.put("李四", 88);
scores.put("王五", 92);
System.out.println("===== 遍历所有key =====");
for (String key : scores.keySet()) {
System.out.println("key: " + key);
}
方式2:遍历value
System.out.println("===== 遍历所有value =====");
for (Integer value : scores.values()) {
System.out.println("value: " + value);
}
方式3:遍历key-value(最常用)
System.out.println("===== 遍历key-value =====");
for (Map.Entry entry : scores.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + " = " + value);
}
方式4:Java 8+的forEach
System.out.println("===== forEach方式 =====");
scores.forEach((key, value) -> {
System.out.println(key + " = " + value);
});
TreeMap的使用
TreeMap基于红黑树实现,会按照key进行排序。
创建TreeMap
import java.util.TreeMap;
import java.util.Map;
Map treeMap = new TreeMap<>();
treeMap.put("banana", 2);
treeMap.put("apple", 5);
treeMap.put("orange", 3);
System.out.println(treeMap);
// 输出:{apple=5, banana=2, orange=3}
// 按key的字母顺序排列
TreeMap特有方法
TreeMap treeMap = new TreeMap<>();
treeMap.put("banana", 2);
treeMap.put("apple", 5);
treeMap.put("orange", 3);
// 获取第一个和最后一个key
System.out.println("第一个key: " + treeMap.firstKey());
System.out.println("最后一个key: " + treeMap.lastKey());
// 获取小于等于指定key的最大key
System.out.println("floorKey('orange'): " + treeMap.floorKey("orange"));
// 获取大于等于指定key的最小key
System.out.println("ceilingKey('orange'): " + treeMap.ceilingKey("orange"));
LinkedHashMap的使用
LinkedHashMap维护插入顺序,适合需要保持元素插入顺序的场景。
创建LinkedHashMap
import java.util.LinkedHashMap;
import java.util.Map;
Map linkedMap = new LinkedHashMap<>();
linkedMap.put("first", 1);
linkedMap.put("second", 2);
linkedMap.put("third", 3);
System.out.println(linkedMap);
// 输出:{first=1, second=2, third=3}
// 保持插入顺序
HashMap、TreeMap、LinkedHashMap对比
| 特性 | HashMap | LinkedHashMap | TreeMap |
|---|---|---|---|
| 底层数据结构 | 哈希表 | 哈希表+链表 | 红黑树 |
| 顺序 | 无序 | 插入顺序 | key排序顺序 |
| 查找速度 | O(1) | O(1) | O(log n) |
| key限制 | 可为null | 可为null | 不能为null |
| 适用场景 | 最常用 | 需要保持顺序 | 需要排序 |
Map常用方法汇总
| 方法 | 说明 |
|---|---|
| put(K key, V value) | 添加键值对 |
| get(Object key) | 通过key获取value |
| getOrDefault(K key, V defaultValue) | 安全获取,不存在返回默认值 |
| remove(Object key) | 删除指定key的键值对 |
| clear() | 清空所有键值对 |
| containsKey(Object key) | 判断是否包含指定key |
| containsValue(Object value) | 判断是否包含指定value |
| keySet() | 获取所有key的集合 |
| values() | 获取所有value的集合 |
| entrySet() | 获取所有键值对的集合 |
| size() | 获取键值对数量 |
| isEmpty() | 判断是否为空 |
实战练习
练习:单词计数
import java.util.HashMap;
import java.util.Map;
public class WordCount {
public static void main(String[] args) {
String[] words = {"apple", "banana", "apple", "orange", "banana", "apple"};
Map countMap = new HashMap<>();
for (String word : words) {
countMap.put(word, countMap.getOrDefault(word, 0) + 1);
}
System.out.println("===== 单词计数结果 =====");
for (Map.Entry entry : countMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
小结
- Map存储键值对(key-value),通过key快速查找value
- HashMap最常用,查找效率高,key无序
- LinkedHashMap保持插入顺序
- TreeMap按key排序
- 遍历方式:keySet()、values()、entrySet()、forEach
☕ Java 在线代码编辑器
📝 运行结果