IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Stream按对象某属性去重的方案 -> 正文阅读

[Java知识库]Stream按对象某属性去重的方案

1.Collectors.collectingAndThen

  • 这是Stream中的一个收集器,相比普通的Collectors.toList、Collectors.groupingBy等收集器
  • Collectors.collectingAndThen还可以在收集之后进行某种操作
  • 多一个形参,用于写function函数(有入参有出参)

源码分析

举例说明collectingAndThen:

List按某属性去重,返回List

例1

2.本质流程

使用Collectors.collectingAndThen的本质是:先把new Set( list ) 获取一个Set,然后new List ( set )返回List

3. 如何用Set去重

用TreeSet和HashSet都能去重,只是去重的逻辑不一样。先看二者的存储逻辑:

  • Hashset是通过复写hashCode()方法和equals()方法来保证的。
  • 而Treeset是通过Compareable接口的compareto方法来保证的。同理可以用Comparator来定制排序

3.1TreeSet去重

①自然排序Comparable接口

@Data
public class DtoReq implements Comparable {

 private String userName;
 private String password;
 
 @Override
 public int compareTo(Object o) {
  DtoReq req =  (DtoReq)o;
  return req.getUserName().compareTo(this.getUserName());
 }
}
  • 代码逻辑即:对userName字段进行比较,且TreeSet的去重功能不需要关注顺序,谁比谁都一样
  • 不过这种方式相当于写死了,耦合度太高

去重代码

ArrayList<DtoReq> collect = arrayList.stream().collect(
    Collectors.collectingAndThen(
        Collectors.toCollection(
            TreeSet::new),ArrayList::new)
);

new TreeSet(arrayList)时构造器会自动去比较Comparable接口的compareTo方法,而达到去重的效果

②定制排序Comparator接口

  • 当元素的类型没实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序

  • 应该用匿名对象重写compare方法 或用lambda表达式调用Comparator.comparing方法

    @Data
    public class DtoReq {

    private String userName;
    private String password;

    }

匿名对象重写compare方法

/**
 * 定制排序Comparator对象,封装了排序的逻辑
 * 这里的泛型千万不能省,会用作lambda表达式的类型推断
 */
Comparator<DtoReq> comparator = new Comparator() {
  @Override
  public int compare(Object o1, Object o2) {
    DtoReq r1 = (DtoReq)o1;
    DtoReq r2 = (DtoReq)o2;
    return r1.getUserName().compareTo(r2.getUserName());
  }

};

ArrayList<DtoReq> collect = arrayList.stream().collect(
    Collectors.collectingAndThen(
        Collectors.toCollection(
            () -> new TreeSet<>(comparator)
        )
        , ArrayList::new)
);

静态方法comparing+lambda表达式

不需要new那个Comparator对象并重写其compare方法,直接调用静态方法Comparator.comparing方法,其形参是方法引用,意为:针对某属性进行排序,当然这里不是为了排序,只是为了去重

ArrayList<DtoReq> collect = arrayList.stream().collect(
    Collectors.collectingAndThen(
        Collectors.toCollection(
            () -> new TreeSet<>(Comparator.comparing(DtoReq::getUserName))
        )
        , ArrayList::new)
);

3.2HashSet去重

  • 利用HashSet去重,只需要重写其equals()hashCode()方法
  • 而好巧不巧lombok的@data注解提供了这两个方法的重写

lombok引入@data

@Data
public class DtoReq {

 private String userName;
 private String password;

}

此时就已经有了equals()和hashCode()方法,直接用就好

直接调HashSet构造器

ArrayList<DtoReq> collect = arrayList.stream().collect(
    Collectors.collectingAndThen(
        Collectors.toCollection(
            () -> new HashSet<>()
        )
        , ArrayList::new)
);

方法引用进行优化

ArrayList<DtoReq> collect = arrayList.stream().collect(
    Collectors.collectingAndThen(
        Collectors.toCollection(
            HashSet::new) , ArrayList::new)
);

4.去重逻辑

5.为什么不用distinct()

Stream流有一个distinct()方法可以去重,但是这个distinct()是直接调用当前流中存储对象的equals()方法,而Set会计算哈希值
List去重以及效率分析

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-28 11:39:48  更:2022-04-28 11:42:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:28:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码