Java Map 高效、实用高频方法大全(JDK8+ 重点)

📅 2026/7/10 22:13:02 👁️ 阅读次数 📝 编程学习
Java Map 高效、实用高频方法大全(JDK8+ 重点)

一、新增核心流式 / 函数式高效方法(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才改成10

3.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());