Lambda使用——Stream流合并、分组内对象数据合并

本文介绍如何利用Java 8的Lambda表达式对多个接口返回的数据按省份ID进行分组合并,通过具体实例展示了如何将不同接口返回的字段合并到同一实体中,并提供了完整的测试代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

之前写过《Lambda使用——JDK8新特性》,现在有一个分组合并的需求正好拿来小试牛刀。

需求

数据出自许多接口数据,需要将几个接口数据根据省份id进行分组合并。举例说明:
A接口返回List里面有值的的字段为:provinceId、field1、field2、field3
B接口返回List里面有值的的字段为:provinceId、field4、field5、field6
C接口返回List里面有值的的字段为:provinceId、field7、field8、field9

最终实现的效果是返回一个最终的list,里面的每一个实体值是上面所有字段合并后的值(provinceId、field1、field2、field3、field4、field5、field6、field7、field8、field9)

代码实现

依赖引入

本文用的是junit测试类

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
            <version>5.5.6</version>
        </dependency>
    </dependencies>

设计实体类

实体类包含了所有的字段

package com.leo;

import lombok.Data;
import java.io.Serializable;
@Data
public class TestObj implements Serializable {
    private static final long serialVersionUID = 1L;
    String provinceId;
    String field1;
    String field2;
    String field3;
    String field4;
    String field5;
    String field6;
    String field7;
    String field8;
    String field9;
}

测试代码

    /**
     * 测试类
     */
    @Test
    public void streamConcat2() {

        TestObj t0 = new TestObj();
        t0.setProvinceId("000");
        t0.setField1("1");
        t0.setField2("2");
        t0.setField3("3");

        TestObj t1 = new TestObj();
        t1.setProvinceId("100");
        t1.setField1("1");
        t1.setField2("2");
        t1.setField3("3");

        TestObj t2 = new TestObj();
        t2.setProvinceId("100");
        t2.setField4("4");
        t2.setField5("5");
        t2.setField6("6");

        TestObj t3 = new TestObj();
        t3.setProvinceId("100");
        t3.setField7("7");
        t3.setField8("8");
        t3.setField9("9");

        TestObj t4 = new TestObj();
        t4.setProvinceId("102");
        t4.setField7("7");
        t4.setField8("8");
        t4.setField9("9");

        List<TestObj> list1 = new ArrayList<>();
        list1.add(t0);
        list1.add(t1);

        List<TestObj> list2 = new ArrayList<>();
        list2.add(t2);

        List<TestObj> list3 = new ArrayList<>();
        list3.add(t3);
        list3.add(t4);

        // 根据省份id进行分组,将同一个省的不同字段合并成一条数据对象
        List<TestObj> list = Stream.concat(Stream.concat(list1.stream(), list2.stream()), list3.stream())
                .filter(e -> e != null)
                .collect(Collectors.toMap(TestObj::getProvinceId, a -> a, (o1, o2) -> {
                    try {
                        // Hutool 的属性拷贝,最后一个参数是设置为null的字段不拷贝
                        BeanUtil.copyProperties(o1, o2, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return o2;
                })).values().stream().collect(Collectors.toList());

        // 打印数据
        list.stream().forEach(System.out::println);
    }
}

测试结果:

TestObj(provinceId=000, field1=1, field2=2, field3=3, field4=null, field5=null, field6=null, field7=null, field8=null, field9=null)
TestObj(provinceId=100, field1=1, field2=2, field3=3, field4=4, field5=5, field6=6, field7=7, field8=8, field9=9)
TestObj(provinceId=102, field1=null, field2=null, field3=null, field4=null, field5=null, field6=null, field7=7, field8=8, field9=9)

以每个省id作为进行数据分组,一个省只有一行数据,将其他有值的字段合并到这一行数据上

### Java Lambda 表达式与 Stream 的操作 在 Java 中,Lambda 表达式和 Stream API 的结合使用能够简化集合数据的处理过程并提高代码可读性。通过这些特性,开发者可以编写更为简洁高效的程序。 #### 创建 Stream 并执行基本操作 下面是一个简单的例子展示如何创建 `Stream` 对象以及应用一些常见的中间操作(如过滤、映射)和终端操作: ```java import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class Demo { public static void main(String[] args) { List<String> names = Arrays.asList("张无忌", "赵敏", "周芷若"); // 将列表转换成,并对其进行一系列变换最终收集结果 List<String> filteredNames = names.stream() .filter(name -> name.length() > 3) .map(String::toUpperCase) .collect(Collectors.toList()); System.out.println(filteredNames); } } ``` 这段代码展示了几个重要的概念:从集合生成(`stream()`), 进行条件筛选 (`filter`) 和字符串大小写转换 (`map`). 最终调用 `collect` 来结束整个水线并将结果保存回一个新的列表中[^4]. #### 合并两个 Stream 实例 另一个有趣的案例是如何将多个 `Stream` 结合在一起形成新的序列: ```java import java.util.stream.Stream; public class ConcatStreamsExample { public static void main(String[] args) { Stream<String> streamA = Stream.of("张无忌"); Stream<String> streamB = Stream.of("张翠山"); // 使用 concat 方法连接两条独立的数据 Stream<String> combinedStream = Stream.concat(streamA, streamB); combinedStream.forEach(System.out::println); } } ``` 这里利用了静态导入的方式让代码看起来更加整洁;同时演示了怎样通过 `concat` 函数轻松地把不同源头产生的元素汇集起来输出[^1]. #### 排序操作 当涉及到对有序性的需求时,也可以借助于 `sorted` 方法来完成升序或降序排列的任务: ```java List<Integer> numbers = Arrays.asList(7, 2, 9, 5, 1); numbers.stream().sorted((a,b)->b-a).forEach(System.out::print); // 输出按逆序排列后的整数数组 ``` 此片段说明了即使是在匿名内部类难以施展拳脚的地方——比如比较器逻辑里头,Lambda同样能发挥巨大作用.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leo825...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值