【141期】JDK8 Stream 操作 collectingAndThen:根据对象的属性去重

点击上方“Java精选”,选择“设为星标”

别问别人为什么,多问自己凭什么!

下方留言必回,有问必答!

每天 08:00 更新文章,每天进步一点点...

ExportTemperatureDto实体对象:

@Getter
@Setter
@ToString
public class ExportTemperatureDto {
    private String name;
    private Double morningTemperature;
    private Double afternoonTemperature;
    private String classId;
    private String gradeId;
    private Integer personId;
}

在一个ExportTemperatureDto的集合中,根据personId属性去重,生成一个新的集合。

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;
 
public class StreamTest {
 
    public static void main(String[] args) {
        List<ExportTemperatureDto> temperatureList = Lists.newArrayList();
        temperatureList.add(new ExportTemperatureDto(1, "haha"));
        temperatureList.add(new ExportTemperatureDto(2, "haha"));
        temperatureList.add(new ExportTemperatureDto(3, "haha"));
        temperatureList.add(new ExportTemperatureDto(4, "haha"));
 
        temperatureList.add(new ExportTemperatureDto(1, "hahaasdas"));
        temperatureList.add(new ExportTemperatureDto(2, "hahaasdas"));
 
        List<ExportTemperatureDto> result = temperatureList.stream()
                .collect(
                        collectingAndThen(
                                toCollection(
                                        () -> new TreeSet<>(comparing(ExportTemperatureDto::getPersonId))
                                ),
                                ArrayList::new
                        )
                );
 
        result.forEach(System.out::println);
 
        /*
            输出结果为:
                personId为1的,其名称为haha
                personId为2的,其名称为haha
            因为TreeSet底层是使用TreeMap进行实现的,传入了根据getPersonId进行比较的比较器
            在判断personId相同时,其比较结果为0,然后就会替换其value值,而key值是不会变化的,
            又因为TreeSet是将传入的元素作为key的,所以使用TreeSet时,当比较器比较的结果相同时,以不会将原来的值替换成比较后的值
         */
 
    }
}

知其然知其所以然,这个stream流的操作看起来还是有点难度的,这里记录一下。

推荐:Java进阶学习资料

使用到了collectingAndThen完成根据属性进行去重的操作,对于该去重操作的关键使用到了collectingAndThen、toCollection、TreeSet,有点难以理解,当时我也是懵逼的,这里记录一下,以后肯定还会用的到。

理解根据对象的属性进行去重的核心是,将集合放到TreeSet中,然后再将TreeSet转为List, 其中TreeSet要传入一个根据哪个属性进行比较的比较器,然后使用public ArrayList(Collection<? extends E> c)将TreeSet放入构造器中生成List。

上面的Stream操作可以使用普通的集合:

TreeSet<ExportTemperatureDto> treeSet = new TreeSet<>(Comparator.comparing(ExportTemperatureDto::getPersonId));
for (ExportTemperatureDto temperatureDto : temperatureList){
    treeSet.add(temperatureDto);
}
List<ExportTemperatureDto> result2 =  new ArrayList<>(treeSet);

只要能够理解普通集合怎么操作的,那么使用Stream流操作时,就是要看对于API的使用是否熟悉,其实这个才是关键,只有理解了collectingAndThen、toCollection、JDK8的匿名函数这样内容,才能看懂这个式子。

下面就简单介绍一下:

首先说一下collectingAndThen方法的使用-------先进行结果集的收集,然后将收集到的结果集进行下一步的处理 ,红字的两句话是理解collectingAndThen的关键,首先看一下collectingAndThen需要传递的参数:

public static<T,A,R,RR> Collector<T,A,RR> 
         collectingAndThen(Collector<T,A,R> downstream,
         Function<R,RR> finisher)

可以看到第一个参数是Collector接口的子类,所以还是对于对于Collector的处理,Collectors工具类里面的toList()toSet()joining()mapping()collectingAndThen()等几乎所有的方法都可以使用,这样感觉这个collectingAndThen就很强大了,可以嵌套的去使用。

第二个参数是一个Function函数,熟悉的同学都知道,Function函数是这样的:R apply(T t),这个也是理解上面去重式子的关键,原来我想的是ArrayList::new调用的无参的构造方法,其实他调用的ArrayList的有参构造方法,

public ArrayList(Collection<? extends E> c)

调用的是上面那个构造方法,这样就很清晰,就是把第一个参数downstream的结果,交给第二个参数Function函数的参数里面,R apply(T t),也就是将结果设置成t。

对于toCollection是一个通用的转为集合的操作,当然在Collectors类里面也有toList()toSet()方法,但是都不满足于使用TreeSet来收集集合的方法,所以使用toCollection是一个通用的方法,使用TreeSet进行收集,然后传入根据哪个属性进行比较的比较器,这样就可以了。

作者:goodluckwj

blog.csdn.net/qq_35634181/article/details/108867857

精品资料,超赞福利!

>>Java精选面试题<< - 小程序,3000+ 道面试题在线刷,最新、最全 Java 面试题!

706cddd5af8e291fc1b8a838039d3dfb.png

8a198fe852126a9a32ef6aa5135f8c9b.png

期往精选  点击标题可跳转

【132期】面试官:Java 8 数据过滤,removeIf 和 filter 有什么区别?

【133期】面试官:TCP 连接大量 TIME_WAIT 状态 ,对业务有什么影响?如何处理?

【134期】技术总监问:如何设计群聊消息的已读未读功能?

【135期】面试官问:为什么要合并 HTTP 请求,实现batch call?

【136期】面试官:Spring AOP、AspectJ、CGLIB ?它们有什么关系?

【137期】面试官问:RocketMQ 与 Kafka 对比,谈谈两者的差异?

【138期】手撸 websocket + netty 实时视频弹幕交互功能(Java版附源码)

【139期】面试官问:一般后端接口都测试什么?怎么测?

文章有帮助的话,在看,转发吧!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值