java stream distinct根据list某个字段去重

项目场景:

java stream distinct根据list某个字段去重,普通List简单去重:

java 复制代码
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class TestMain {
	public static void main(String[] args) {
        List<String> names = Arrays.asList("张三", "李四", "王五", "张三", "李四");
        
        // 使用Stream的distinct()方法进行去重操作
        List<String> distinctNames = names.stream().distinct().collect(Collectors.toList());

        System.out.println("原始列表:" + names);
        System.out.println("去重后的列表:" + distinctNames);
    }
}

很显然这种满足不了需求,我们List里的是实体对象,这里的是字符串。


前提基础:

首先创建了一个Student类,该类包含id、name、age三个字段,使用了注解@Data,我们想根据学生的name去重。

java 复制代码
import lombok.Data;

@Data
public class Student {
	
    public Student(Integer id, String name, Integer age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}
    
	private Integer id;
    private String name;
    private Integer age;
}

解决方案:

一、Stream流 + TreeSet(推荐)

根据学生的name去重,原理:

1、首先使用Stream API对list进行转换成流,使用toCollection方法将流中的元素放入一个TreeSet集合中,通过TreeSet实现对name字段去重;

2、然后使用collectingAndThen方法将TreeSet集合转换成ArrayList集合;

用普通的list对象来操作需要分为两步操作,这里我们使用了Stream API提供的collect方法和Collectors类的两个静态方法toCollection和collectingAndThen来进行去重操作,不需要写繁琐的for循环,更加简洁高效。

java 复制代码
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;

public class TestMain {
	public static void main(String[] args) {
		List<Student> list = new ArrayList<>();
		list.add(new Student(1, "张三", 13));
		list.add(new Student(2, "李四", 14));
		list.add(new Student(3, "张三", 15));
		list.add(new Student(4, "王五", 16));
		list.add(new Student(5, "李四", 17));

		List<Student> distinctList = list.stream().collect(
		    Collectors.collectingAndThen(
		        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getName))), ArrayList<Student>::new)
		);
		System.out.println(distinctList);
    }
}

二、Stream流 + toMap

根据学生的name去重,原理:

1、首先使用Stream API对list进行转换成流,使用Collectors.toMap方法将对象流转换为 Map,其中键是 name 字段,值是对象本身。当遇到重复的键时,我们使用合并函数 (p1, p2) -> p1 来选择保留哪个值;

2、然后通过提取 Map 的值集合,我们获得了去重后的结果。将集合转换成List集合;

用普通的list对象来操作需要分为两步操作,这里我们使用了Stream API来操作,不需要写繁琐的for循环,更加简洁高效。注意Map集合是无序的,所以最后打印的结果是无序的。

java 复制代码
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class TestMain {
	public static void main(String[] args) {
		List<Student> list = new ArrayList<>();
		list.add(new Student(1, "张三", 13));
		list.add(new Student(2, "李四", 14));
		list.add(new Student(3, "张三", 15));
		list.add(new Student(4, "王五", 16));
		list.add(new Student(5, "李四", 17));

		List<Student> distinctList = list.stream()
		        .collect(Collectors.toMap(Student::getName, Function.identity(), (p1, p2) -> p1))
		        .values()
		        .stream()
		        .collect(Collectors.toList());
		
		System.out.println(distinctList);
    }
}

三、重写equals和hashCode

Student类在原来的基础上,重写equals和hashCode,根据学生的name去重

java 复制代码
import java.util.Objects;
import lombok.Data;

@Data
public class Student {
	
    public Student(Integer id, String name, Integer age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}
    
	private Integer id;
    private String name;
    private Integer age;
    
    // 重写 equals 和 hashCode 方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}
java 复制代码
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class TestMain {
	public static void main(String[] args) {
		List<Student> list = new ArrayList<>();
		list.add(new Student(1, "张三", 13));
		list.add(new Student(2, "李四", 14));
		list.add(new Student(3, "张三", 15));
		list.add(new Student(4, "王五", 16));
		list.add(new Student(5, "李四", 17));

		List<Student> distinctList = list.stream().distinct().collect(Collectors.toList());
		
		System.out.println(distinctList);
    }
}
相关推荐
月亮不月亮20 分钟前
月亮商场购物打折Java
java·eclipse
guozhetao30 分钟前
【ST表、倍增】P7167 [eJOI 2020] Fountain (Day1)
java·c++·python·算法·leetcode·深度优先·图论
技术思考者31 分钟前
基础很薄弱如何规划考研
java·经验分享·考研
●VON1 小时前
重生之我在暑假学习微服务第二天《MybatisPlus-下篇》
java·学习·微服务·架构·mybatis-plus
老华带你飞1 小时前
口腔助手|口腔挂号预约小程序|基于微信小程序的口腔门诊预约系统的设计与实现(源码+数据库+文档)
java·数据库·微信小程序·小程序·论文·毕设·口腔小程序
hqxstudying1 小时前
J2EE模式---服务层模式
java·数据库·后端·spring·oracle·java-ee
GM_8281 小时前
【最新最完整】SpringAI-1.0.0开发MCP Server,搭建MCP Client 实战笔记(进阶+详细+完整代码)
java·后端·ai编程·springai·mcp
都叫我大帅哥1 小时前
Java DelayQueue:时间管理大师的终极武器
java
秋千码途1 小时前
小架构step系列27:Hibernate提供的validator
java·spring·架构·hibernate
都叫我大帅哥1 小时前
TOGAF迁移规划阶段全解密:从菜鸟到达人的通关秘籍
java