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中,或者该键的值为nullmerge()方法直接将值绑定到该键,而不会调用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)的合并操作。

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

相关推荐
小羊没烦恼!2 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里2 天前
java中的继承和多态的区别
java
小羊没烦恼!2 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕2 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖2 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时2 天前
01-06-A-JVM排查实战详解
java·jvm
伞伞悦读2 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
vipxieliang2 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
C语言小火车2 天前
C/C++ 为什么需要编译器?
开发语言·c++