256. Java 集合 - 掌握 Java 的 merge () 方法:提升 Map 操作效率与灵活性的关键

文章目录

256. Java 集合 - 掌握 Java 的 merge () 方法:提升 Map 操作效率与灵活性的关键

在Java中,处理Map集合时,我们经常需要执行一些涉及值聚合和修改的操作。对于这些任务,computeIfAbsent() 和 merge()方法提供了非常有效的解决方案。

Merging Values(合并值)

computeIfAbsent()模式非常适合处理那些值是其他值聚合的情况。例如,当我们将多个值累积到一个可变集合(如ArrayList)中时,computeIfAbsent()可以方便地实现这一点。然而,这个模式有一个前提条件:支持聚合的结构必须是可变的,比如ArrayList。但当我们希望聚合的值是不可变的(如String),这时computeIfAbsent()就不再适用了。

为了应对这种情况,Java提供了一个非常有用的方法:merge()。merge()方法允许我们将新值合并到已经存在的值中,或者在不存在该键时直接绑定新值。

merge() 方法的工作原理

merge()方法接受三个参数:

  1. key(键):表示你要操作的Map的键。
  2. value(值):你想要绑定到键的值。
  3. remapping BiFunction(重新映射的BiFunction):这是一个函数,接受当前的键值对中的"现有值"和"新值",并返回一个新的值来替换原来的值。

工作流程

  • 如果键不在Map中,或者该键的值为null,merge()方法直接将值绑定到该键,而不会调用remapping函数。
  • 如果键已经存在并且有一个非null值,merge()方法会调用remapping函数,传入当前的值和新的值。remapping函数返回的值会替代原来的值。
  • 如果remapping函数返回null,则该键会从Map中删除。

示例:合并字符串

假设你有一个字符串列表,你想根据字符串的长度将这些字符串分类,并且希望将长度相同的字符串合并为一个字符串,通过逗号分隔。

java 复制代码
List<String> strings = List.of("one", "two", "three", "four", "five", "six", "seven");
Map<Integer, String> map = new HashMap<>();

for (String word : strings) {
    int length = word.length();
    map.merge(length, word, (existingValue, newWord) -> existingValue + ", " + newWord);
}

map.forEach((key, value) -> System.out.println(key + " :: " + value));

运行结果:

java 复制代码
3 :: one, two, six
4 :: four, five
5 :: three, seven

解释:

  1. 首次合并 :当长度为3的字符串(如"one")首次出现时,merge()方法会将其添加到Map中。
  2. 已有键时的合并 :当相同长度的其他字符串(如"two"和"six")出现时,merge()会调用remapping函数,将现有值(如"one")与新值(如"two")合并为一个字符串:"one, two"。然后它会继续合并下一个字符串。

选择merge()的原因

使用merge()方法相对于直接使用putIfAbsent()或computeIfAbsent(),具有更高的灵活性。尤其是在需要合并值的情况下,merge()不仅仅是添加新的值,它还提供了更多控制的能力,尤其是在已有值时如何合并。

性能考虑

在computeIfAbsent()和merge()方法中,你可能会注意到Lambda表达式的参数总是能够直接从上下文中获取。这些Lambda表达式会捕获上下文中的变量,因此推荐尽量避免使用捕获上下文的Lambda,而是使用非捕获Lambda,以提高性能。

总结

  • computeIfAbsent() :适用于通过键生成新的值(如使用List等可变类型作为值),可以避免重复创建对象。
  • merge() :适用于在键存在时合并现有值与新值,或在键不存在时直接设置新值,适合不可变对象(如String)的合并操作。

这两种方法都可以帮助我们高效地处理复杂的映射操作,减少代码冗余,提高代码的可维护性和性能。

相关推荐
蹊黎1 分钟前
C++中vector类的部分简单实现
开发语言·c++·visual studio
驭渊的小故事6 分钟前
MyBatis XML 开发实战:从配置到 CRUD 全解析
xml·java·mybatis
哦虎!5 小时前
【JavaEE】网络初识
java
for_ever_love__5 小时前
MySQL ORDER BY 排序优化:从 Using filesort 到索引有序扫描(含双路 / 单路排序原理)
java·mysql·优化·存储·by·order·filesort
程序猿追6 小时前
kotlin-retry 接入鸿蒙后,怎样确认它真的会停止重试
开发语言·kotlin·harmonyos
我是人✓6 小时前
Java文件上传三方式对比:从传统到SpringBoot
java·开发语言
智能直播6 小时前
网络RTMP拉流不卡顿、声音不同步,一文讲透缓冲区、时间戳
开发语言·ffmpeg·php·音视频·视频编解码
欣栀♡6 小时前
JVM 频繁 Full GC 先看日志括号里的 cause,jstat 的 FGC 在 JDK 8 上会骗人
java·jvm
IT研究室7 小时前
最新计算机毕业设计选题推荐-基于spring boot的葡萄酒文化宣传网站-网站-文档指导-Java-springboot
java·spring boot·课程设计
慧都小项7 小时前
MyEclipse 中创建和测试 JAX-RS REST 接口:从项目配置到 REST Explorer
java·restful·myeclipse·jax-rs