Stream流-JDK8Stream操作collectingAndThen:根据对象的属性去重-《Java笔记》

admin 2025-10-19 02:38:54 编程 来源:ZONE.CI 全球网 0 阅读模式

    Java StreamExportTemperatureDto实体对象:

    1. @Getter
    2. @Setter
    3. @ToString
    4. public class ExportTemperatureDto {
    5. private String name;
    6. private Double morningTemperature;
    7. private Double afternoonTemperature;
    8. private String classId;
    9. private String gradeId;
    10. private Integer personId;
    11. }

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

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

    知其然知其所以然,这个stream流的操作看起来还是有点难度的。使用到了collectingAndThen完成根据属性进行去重的操作,对于该去重操作的关键使用到了collectingAndThentoCollectionTreeSet,有点难以理解。理解根据对象的属性进行去重的核心是,将集合放到TreeSet中,然后再将TreeSet转为List, 其中TreeSet要传入一个根据哪个属性进行比较的比较器,然后使用public ArrayList(Collection<? extends E> c)将TreeSet放入构造器中生成List。上面的Stream操作可以使用普通的集合:

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

    只要能够理解普通集合怎么操作的,那么使用Stream流操作时,就是要看对于API的使用是否熟悉,其实这个才是关键,只有理解了collectingAndThentoCollection、JDK8的匿名函数这样内容,才能看懂这个式子。下面就简单介绍一下:首先说一下collectingAndThen方法的使用———-先进行结果集的收集,然后将收集到的结果集进行下一步的处理,红字的两句话是理解collectingAndThen的关键,首先看一下collectingAndThen需要传递的参数:

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

    可以看到第一个参数是Collector接口的子类,所以还是对于对于Collector的处理,Collectors工具类里面的toList()toSet()joining()mapping()collectingAndThen()等几乎所有的方法都可以使用,这样感觉这个collectingAndThen就很强大了,可以嵌套的去使用。第二个参数是一个Function函数,熟悉的同学都知道,Function函数是这样的:R apply(T t),这个也是理解上面去重式子的关键,原来想的是ArrayList::new调用的无参的构造方法,其实他调用的ArrayList的有参构造方法,

    1. public ArrayList(Collection<? extends E> c)

    调用的是上面那个构造方法,这样就很清晰,就是把第一个参数downstream的结果,交给第二个参数Function函数的参数里面,R apply(T t),也就是将结果设置成t。对于toCollection是一个通用的转为集合的操作,当然在Collectors类里面也有toList()toSet()方法,但是都不满足于使用TreeSet来收集集合的方法,所以使用toCollection是一个通用的方法,使用TreeSet进行收集,然后传入根据哪个属性进行比较的比较器,这样就可以了。

    以太坊cppgolang区别 编程

    以太坊cppgolang区别

    以太坊是一种去中心化的开源平台,它采用智能合约技术,旨在构建和运行不受干扰的分布式应用程序。作为目前最受欢迎的区块链平台之一,以太坊提供了多种编程语言的支持,其
    progolang 编程

    progolang

    Go语言(Golang)是由Google开发的一门静态类型编程语言。作为一名专业的Golang开发者,我深知这门语言的优势和特点。在本文中,我将介绍Golang
    golangn个发送者 编程

    golangn个发送者

    Golang是一种开源的编程语言,由Google团队开发,旨在提高程序的并发性和简化软件开发过程。在Go语言中,有时需要向多个接收者发送信息。本文将介绍如何在G
    golang技能图谱 编程

    golang技能图谱

    从互联网行业的快速发展到人工智能技术的日益成熟,各种编程语言也应运而生。而在这众多的编程语言中,Golang(即Go)作为一门强大且高效的开发语言备受关注。Go
    评论:0   参与:  10