码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 分享几种 Java8 中通过 Stream 对列表进行去重的方法


    几种列表去重的方法

    在这里我来分享几种列表去重的方法,算是一次整理吧,如有纰漏,请不吝赐教。

    1. Stream 的distinct()方法

    distinct()是Java 8 中 Stream 提供的方法,返回的是由该流中不同元素组成的流。distinct()使用 hashCode() 和 eqauls() 方法来获取不同的元素。因此,需要去重的类必须实现 hashCode() 和 equals() 方法。换句话讲,我们可以通过重写定制的 hashCode() 和 equals() 方法来达到某些特殊需求的去重。

    distinct() 方法声明如下:

    1. Stream distinct();
    2. 复制代码

    1.1 对于 String 列表的去重

    因为 String 类已经覆写了 equals() 和 hashCode() 方法,所以可以去重成功。

    1. @Test
    2. public void listDistinctByStreamDistinct() {
    3. // 1. 对于 String 列表去重
    4. List<String> stringList = new ArrayList<String>() {{
    5. add("A");
    6. add("A");
    7. add("B");
    8. add("B");
    9. add("C");
    10. }};
    11. out.print("去重前:");
    12. for (String s : stringList) {
    13. out.print(s);
    14. }
    15. out.println();
    16. stringList = stringList.stream().distinct().collect(Collectors.toList());
    17. out.print("去重后:");
    18. for (String s : stringList) {
    19. out.print(s);
    20. }
    21. out.println();
    22. }
    23. 复制代码

    结果如下:

    1. 去重前:AABBC
    2. 去重后:ABC
    3. 复制代码

    1.2 对于实体类列表的去重

    注:代码中我们使用了 Lombok 插件的 @Data注解,可自动覆写 equals() 以及 hashCode() 方法。

    1. /**
    2. * 定义一个实体类
    3. */
    4. @Data
    5. public class Student {
    6. private String stuNo;
    7. private String name;
    8. }
    9. 复制代码
    1. @Test
    2. public void listDistinctByStreamDistinct() throws JsonProcessingException {
    3. ObjectMapper objectMapper = new ObjectMapper();
    4. // 1. 对于 Student 列表去重
    5. List studentList = getStudentList();
    6. out.print("去重前:");
    7. out.println(objectMapper.writeValueAsString(studentList));
    8. studentList = studentList.stream().distinct().collect(Collectors.toList());
    9. out.print("去重后:");
    10. out.println(objectMapper.writeValueAsString(studentList));
    11. }
    12. 复制代码

    结果如下:

    1. 去重前:[{"stuNo":"001","name":"Tom"},{"stuNo":"002","name":"Mike"},{"stuNo":"001","name":"Tom"}]
    2. 去重后:[{"stuNo":"001","name":"Tom"},{"stuNo":"002","name":"Mike"}]
    3. 复制代码

    2. 根据 List 中 Object 某个属性去重

    2.1 新建一个列表出来

    1. @Test
    2. public void distinctByProperty1() throws JsonProcessingException {
    3. // 这里第一种方法我们通过新创建一个只有不同元素列表来实现根据对象某个属性去重
    4. ObjectMapper objectMapper = new ObjectMapper();
    5. List<Student> studentList = getStudentList();
    6. out.print("去重前 :");
    7. out.println(objectMapper.writeValueAsString(studentList));
    8. studentList = studentList.stream().distinct().collect(Collectors.toList());
    9. out.print("distinct去重后:");
    10. out.println(objectMapper.writeValueAsString(studentList));
    11. // 这里我们引入了两个静态方法,以及通过 TreeSet<> 来达到获取不同元素的效果
    12. // 1. import static java.util.stream.Collectors.collectingAndThen;
    13. // 2. import static java.util.stream.Collectors.toCollection;
    14. studentList = studentList.stream().collect(
    15. collectingAndThen(
    16. toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getName))), ArrayList::new)
    17. );
    18. out.print("根据名字去重后 :");
    19. out.println(objectMapper.writeValueAsString(studentList));
    20. }
    21. 复制代码

    结果如下:

    1. 去重前 :[{"stuNo":"001","name":"Tom"},{"stuNo":"001","name":"Tom"},{"stuNo":"003","name":"Tom"}]
    2. distinct去重后:[{"stuNo":"001","name":"Tom"},{"stuNo":"003","name":"Tom"}]
    3. 根据名字去重后 :[{"stuNo":"001","name":"Tom"}]
    4. 复制代码

    2.2 通过 filter() 方法

    我们首先创建一个方法作为 Stream.filter() 的参数,其返回类型为 Predicate,原理就是判断一个元素能否加入到 Set 中去,代码如下:

    1. private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    2. Set<Object> seen = ConcurrentHashMap.newKeySet();
    3. return t -> seen.add(keyExtractor.apply(t));
    4. }
    5. 复制代码

    使用如下:

    1. @Test
    2. public void distinctByProperty2() throws JsonProcessingException {
    3. // 这里第二种方法我们通过过滤来实现根据对象某个属性去重
    4. ObjectMapper objectMapper = new ObjectMapper();
    5. List<Student> studentList = getStudentList();
    6. out.print("去重前 :");
    7. out.println(objectMapper.writeValueAsString(studentList));
    8. studentList = studentList.stream().distinct().collect(Collectors.toList());
    9. out.print("distinct去重后:");
    10. out.println(objectMapper.writeValueAsString(studentList));
    11. // 这里我们将 distinctByKey() 方法作为 filter() 的参数,过滤掉那些不能加入到 set 的元素
    12. studentList = studentList.stream().filter(distinctByKey(Student::getName)).collect(Collectors.toList());
    13. out.print("根据名字去重后 :");
    14. out.println(objectMapper.writeValueAsString(studentList));
    15. }
    16. 复制代码

    结果如下:

    1. 去重前 :[{"stuNo":"001","name":"Tom"},{"stuNo":"001","name":"Tom"},{"stuNo":"003","name":"Tom"}]
    2. distinct去重后:[{"stuNo":"001","name":"Tom"},{"stuNo":"003","name":"Tom"}]
    3. 根据名字去重后 :[{"stuNo":"001","name":"Tom"}]
    4. 复制代码

    3. 总结

    以上便是我要分享的几种关于列表去重的方法,当然这里没有进行更为详尽的性能分析,希望以后会深入底层再重新分析一下。如有纰漏,还望不吝赐教。

  • 相关阅读:
    青龙面板安装及配置
    To B 定位,是要回答好这四个问题
    《linux程序设计》笔记第一章
    机器学习-特征映射方法
    混合云运维解决方案,支持公有云、私有云、信创云等环境
    LSF 集群全面监控:浅析 HPC 基于龙蜥操作系统的迁移替代解决方案
    MinIo使用小结
    零拷贝技术可以加入到计算机组成原理的授课中
    acwing 2811. 最长公共子串(SAM)
    1.10 UML
  • 原文地址:https://blog.csdn.net/BASK2312/article/details/127997246
    • 最新文章
    • 沪漂五周年了:我越来越迷茫了
      Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
      MySQL-Seconds_behind_master的精度误差
      [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
      AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
      Agent OS :五种驯服不确定性的范式
      PortSwigger SQL注入LAB11
      数据库即时编译JIT
      [Begin]AI Learn Data Day 0
      深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    小工具 小游戏
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

    京公网安备 11010502049817号