Map的使用与代码题常用场景详解
一、Map是什么?
Map是Java集合框架中的接口,用于存储键值对(Key-Value) 数据。每个键(Key)唯一对应一个值(Value),类似字典结构。核心实现类:
HashMap
:无序,基于哈希表(JDK8后引入红黑树优化冲突)LinkedHashMap
:保留插入顺序TreeMap
:按键自然排序ConcurrentHashMap
:线程安全(JDK8后改用CAS+synchronized)
二、解决什么问题
- 快速查找:通过键(Key)直接定位值(Value),时间复杂度接近O(1)
- 数据关联:建立两个数据集的映射关系(如用户ID→用户信息)
- 去重计数:利用Key的唯一性实现统计(如词频统计)
三、核心方法
方法 | 说明 |
---|---|
put(K key, V value) | 添加键值对 |
get(Object key) | 根据Key获取Value |
containsKey(Object key) | 判断Key是否存在 |
keySet() | 返回所有Key的集合 |
entrySet() | 返回所有键值对的集合 |
getOrDefault(K key, V defaultValue) | Key不存在时返回默认值(JDK8新增) |
computeIfAbsent(K key, Function f) | Key不存在时通过函数生成Value(JDK8新增) |
四、代码题常用场景
频率统计
java// 统计字符串中字符出现次数 Map<Character, Integer> freq = new HashMap<>(); for (char c : s.toCharArray()) { freq.put(c, freq.getOrDefault(c, 0) + 1); }
索引映射
java// 两数之和:用Map存储<数值, 索引> Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[]{map.get(complement), i}; } map.put(nums[i], i); }
缓存最近访问(LRU)
java// 使用LinkedHashMap实现LRU缓存 Map<Integer, String> cache = new LinkedHashMap<>(16, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > MAX_SIZE; } };
分组聚合
java// 按学生班级分组(JDK8 Stream API) Map<String, List<Student>> groupByClass = students.stream() .collect(Collectors.groupingBy(Student::getClassName));
五、Java示例:单词计数器
java
import java.util.*;
public class WordCounter {
public static void main(String[] args) {
String text = "apple banana apple orange banana apple";
Map<String, Integer> counter = new HashMap<>();
// JDK8增强:合并计数
Arrays.stream(text.split(" "))
.forEach(word -> counter.merge(word, 1, Integer::sum));
// 输出:{orange=1, banana=2, apple=3}
System.out.println(counter);
}
}
六、与类似结构的区别
结构 | 特点 | 适用场景 |
---|---|---|
Map | Key-Value映射,Key唯一 | 需通过Key快速查找Value |
Set | 仅存储Key(基于Map实现) | 元素去重 |
List | 有序集合,可重复 | 按索引访问 |
七、重要注意事项
- 键对象需重写
hashCode()
和equals()
(否则HashMap
无法正确识别Key) HashMap
线程不安全
并发场景用ConcurrentHashMap
或Collections.synchronizedMap()
- 避免在迭代中修改Map
会抛出ConcurrentModificationException
- 初始容量与负载因子java
// 预估数据量1000,负载因子0.75 new HashMap<>(1333, 0.75f); // 容量=1000/0.75≈1333
八、总结
Map是解决关联性数据存储的核心工具,在代码题中常用于:
- 快速查找(如两数之和)
- 频率统计(如字符计数)
- 分组聚合(如按类别分组)
- 缓存实现(如LRU缓存)
掌握HashMap
的核心机制(哈希冲突、红黑树优化)及JDK8新增方法(getOrDefault
、computeIfAbsent
),能显著提升解题效率。建议在算法练习中优先考虑Map解决映射类问题。