Java8-Stream流操作List去重distinct、和指定字段去重

使用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 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}