一、新增核心流式 / 函数式高效方法(JDK8 最强)
1.computeIfAbsent(K key, Function)天花板级方法
场景:不存在则创建,存在直接返回,避免重复判断
map.computeIfAbsent("key", k -> new ArrayList<>()).add("data");
性能:只查一次 map,比get+putIfAbsent少一次哈希查找,分组、缓存、对象初始化首选
2.computeIfPresent(K key, BiFunction)
key 存在才执行更新,不存在不操作,适合增量更新
// 数字累加,key存在才+1
map.computeIfPresent("count", (k, v) -> v + 1);
3.compute(K key, BiFunction)
不管 key 是否存在,统一计算覆盖,支持删除(返回 null 则移除 key)
// 数值翻倍
map.compute("num", (k, v) -> v == null ? 0 : v * 2);
// 返回null直接删除该键
map.compute("del", (k, v) -> null);
4.merge(K key, V value, BiFunction)统计聚合神器
计数、求和、字符串拼接最强方法逻辑:
- key 不存在 → put (value)
- key 存在 → 执行函数,函数返回值作为新 value;返回 null 删除 key
// 单词计数 Map<String, Integer> wordCount = new HashMap<>(); wordCount.merge("java", 1, Integer::sum); wordCount.merge("java", 1, Integer::sum); // java=2 // 字符串拼接 map.merge("msg", "a", String::concat); map.merge("msg", "b", String::concat); // msg="ab"二、安全取值,避免空指针(高效简洁)
1.getOrDefault(Object key, V defaultValue)
不存在返回默认值,无需 if 判空
Integer num = map.getOrDefault("score", 0);2.putIfAbsent(K key, V value)
key 不存在才存入,存在不覆盖,适合初始化缓存
map.putIfAbsent("token", UUID.randomUUID().toString());三、遍历高性能方法(推荐,比 entrySet 老式循环简洁)
1.forEach(BiConsumer)一键遍历,不用迭代器
map.forEach((k, v) -> System.out.println(k + ":" + v));2. 获取视图流式处理(Stream)
// 过滤、转换、收集 Map<String, Integer> filterMap = map.entrySet().stream() .filter(e -> e.getValue() > 10) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); // 只遍历value map.values().stream().filter(...); // 只遍历key map.keySet().stream().filter(...);四、批量操作、数据清理
1.remove(Object key, Object value)精准删除
只有 key&value 同时匹配才删除,避免误删
map.remove("status", 0);2.replace系列
replace(K key, V newValue):key 存在才替换,不存在无操作replace(K key, V oldValue, V newValue):仅原值匹配才替换(原子操作)
map.replace("num", 5, 10); // 值=5才改成103.replaceAll(BiFunction)批量统一修改所有 value
// 所有数字*2 map.replaceAll((k, v) -> v * 2);4.clear()/isEmpty()/containsKey()/containsValue()
基础高频,containsKeyO(1),containsValueO (n) 尽量少用
五、JDK9+ 快速创建不可变 Map(线程安全,性能高)
// 少量键值对 Map<String, Integer> smallMap = Map.of("a", 1, "b", 2); // 超过10个键值对 Map.Entry<String, Integer> e1 = Map.entry("x", 10); Map.Entry<String, Integer> e2 = Map.entry("y", 20); Map<String, Integer> bigMap = Map.ofEntries(e1, e2);特点:不可修改、null 键 / 值报错、底层轻量实现,性能优于 HashMap 初始化
六、高性能分组工具(Collectors.groupingBy)
配合 Stream 实现复杂分组,底层依赖 map 特性
List<User> users = ...; // 按年龄分组 Map<Integer, List<User>> userGroup = users.stream() .collect(Collectors.groupingBy(User::getAge)); // 分组同时计数 Map<Integer, Long> ageCount = users.stream() .collect(Collectors.groupingBy(User::getAge, Collectors.counting()));七、各方法性能对比总结
八、ConcurrentMap 额外原子高效方法(并发场景)
ConcurrentHashMap全部上述方法均为原子操作,多线程不用手动加锁:
- compute/merge/computeIfAbsent 天然线程安全
getOrDefault无锁读取- 替代 synchronized 包裹 map,大幅提升并发吞吐量
九、开发常用实战模板
List 分组缓存
Map<Long, List<Order>> orderMap = new HashMap<>(); orders.forEach(order -> orderMap.computeIfAbsent(order.getUserId(), k -> new ArrayList<>()) .add(order) );数据统计计数
Map<String, Integer> countMap = new HashMap<>(); for (String tag : tagList) { countMap.merge(tag, 1, Integer::sum); }安全取值默认对象
User user = userMap.getOrDefault("id", new User());