Java8-Stream流操作List去重distinct、和指定字段去重(完整实例讲解)

2022-07-28,,,,

使用Java8的Stream的distinct方法去重,我们的对象需要实现hashcode()和equals()方法。

把学生类修改后如下:

public class Student {
    private Long id;
    private String name;
    private int age;
    private Double height;

    public Student(Long id, String name, int age, Double height) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Double getHeight() {
        return height;
    }

    public void setHeight(Double height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(id, student.id) &&
                Objects.equals(name, student.name) &&
                Objects.equals(height, student.height);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, age, height);
    }
}

测试例子:

import com.top.test.dto.Student;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class ListStreamDistinctTest {
    public static void main(String[] args) {
        // 一个集合中放入4个学生对象
        List<Student> list = new ArrayList<>();
        list.add(new Student(10002L, "ZhangSan", 18, 175.2));
        list.add(new Student(10001L, "LiSi", 19, 175.2));
        list.add(new Student(10004L, "Peter", 19, 170.8));
        list.add(new Student(10004L, "Peter", 19, 170.8));

        // 按整个个对象去重
        System.out.println("整个对象去重:");
        list.stream().distinct()
                .forEach(System.out::println);

        // 指定某个字段去重
        System.out.println("指定age属性去重(方法一):");
        list.stream().filter(distinctByKey1(s -> s.getAge()))
                .forEach(System.out::println);

        // 方法二(用循环)
        System.out.println("指定age属性去重(方法二):");
        TreeSet<Student> students = new TreeSet<>(Comparator.comparing(s -> s.getAge()));
        for (Student student : list) {
            students.add(student);
        }
        new ArrayList<>(students)
                .forEach(System.out::println);

        // 方法三:(是方法二的变形),此方法来源于:https://blog.csdn.net/qq_28988969/article/details/81119587
        System.out.println("指定age属性去重(方法三):");
        list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(s -> s.getAge()))), ArrayList::new))
                .forEach(System.out::println);


    }

    // 次方法来源于:https://blog.csdn.net/haiyoung/article/details/80934467
    static <T> Predicate<T> distinctByKey1(Function<? super T, ?> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
}

执行结果:

整个对象去重:
Student{id=10002, name='ZhangSan', age=18, height=175.2}
Student{id=10001, name='LiSi', age=19, height=175.2}
Student{id=10004, name='Peter', age=19, height=170.8}
指定age属性去重(方法一):
Student{id=10002, name='ZhangSan', age=18, height=175.2}
Student{id=10001, name='LiSi', age=19, height=175.2}
指定age属性去重(方法二):
Student{id=10002, name='ZhangSan', age=18, height=175.2}
Student{id=10001, name='LiSi', age=19, height=175.2}
指定age属性去重(方法三):
Student{id=10002, name='ZhangSan', age=18, height=175.2}
Student{id=10001, name='LiSi', age=19, height=175.2}

Lambda表达式和函数式接口看不懂的,可以参考之前的文章:
Java8 Lambda表达式 和 函数式编程 原理详解


沪漂程序员。 坚持写博客,如果觉得还可以的话,给个小星星哦,你的支持就是我创作的动力。

个人微信公众号:“Java尖子生”,阅读更多干货。
关注公众号,领取学习、面试资料。加技术讨论群。


阅读更多我的相关内容
Java8 Lambda表达式 和 函数式编程 原理详解
Java8方法引用,示例讲解
Java8-默认方法和默认静态方法
Java8-Stream流操作List排序(完整实例讲解)

本文地址:https://blog.csdn.net/Kurry4ever_/article/details/109638367

《Java8-Stream流操作List去重distinct、和指定字段去重(完整实例讲解).doc》

下载本文的Word格式文档,以方便收藏与打印。