基于Stream流的去重操作,主要包括下面几种方式:
- distinct 按照对象去重(实现 hashCode()和 equals()方法)
- filter 按照对象属性去重(不需要实现 hashCode()和 equals()方法)
- 利用stream的collectingAndThen+TreeSet去重(推荐)
去重实例对象
@Data
@AllArgsConstructor
public class Student implements Serializable{
private static final long serialVersionUID = 8170834275910515552L;
private String name;
private Integer age;
private Boolean sex;
}
distinct
/**
* distinct 按照对象去重(实现 hashCode()和 equals()方法)
*
* @Param students
*/
public static void distinctHandleRepeat(List<Student> students) {
students.stream().distinct().collect(Collectors.toList()).forEach(System.out::println);
}
filter
/**
* filter 按照对象属性去重(不需要实现 hashCode()和 equals()方法)
* 单属性去重
* 多属性去重(例如: 根据age去重后,再根据sex再次进行去重)
*
* @param students
*/
public static void filterHandleRepeat(List<Student> students) {
students.stream()
.filter(filterByKey(Student::getAge))
.filter(filterByKey(Student::getSex))
.forEach(System.out::println);
}
/**
* putIfAbsent(): key存在时不添加到map并返回value,不存在时则添加返回null
*
* @param keyExtractor
* @param <T>
* @return
*/
public static <T> Predicate<T> filterByKey(Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>(16);
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
TreeSet(推荐)
/**
* 利用stream的collectingAndThen+TreeSet去重
*
* @param students
*/
public static void collectingAndThenHandleRepeat(List<Student> students) {
students.stream()
.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getAge))), ArrayList::new))
.forEach(System.out::println);
}
调用示例
public static void main(String[] args) {
// distinct去重
distinctHandleRepeat(getStudents());
System.out.println("================================================");
// filter去重
filterHandleRepeat(getStudents());
System.out.println("================================================");
// collectingAndThen+TreeSet去重
collectingAndThenHandleRepeat(getStudents());
}
public static List<Student> getStudents() {
List<Student> students = new ArrayList<>();
students.add(new Student("Tom", 25, Boolean.TRUE));
students.add(new Student("Jack", 23, Boolean.TRUE));
students.add(new Student("Top", 22, Boolean.FALSE));
students.add(new Student("Gao", 22, Boolean.FALSE));
students.add(new Student("Top", 22, Boolean.FALSE));
return students;
}
测试结果
Student(name=Tom, age=25, sex=true)
Student(name=Jack, age=23, sex=true)
Student(name=Top, age=22, sex=false)
Student(name=Gao, age=22, sex=false)
================================================
Student(name=Tom, age=25, sex=true)
Student(name=Top, age=22, sex=false)
================================================
Student(name=Top, age=22, sex=false)
Student(name=Jack, age=23, sex=true)
Student(name=Tom, age=25, sex=true)
推荐利用stream的collectingAndThen+TreeSet去重,灵活度和简洁度都较高