直接上代码:(实现了去重加排序的效果)
//换行只是为了方便看
userList.stream().collect(Collectors.collectingAndThen(Collectors
.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getAge))), ArrayList::new));
comparing(比较器)定义的就是去重的所使用的字段,可以使用匿名内部类来写更复杂的去重逻辑。
我们看看单参数的比较器方法实现;如下,可以发现内部实际调用效果类似于(a,b)->a.getXXX.conpareTo(b.getXXX)。
因为Function.apply(field)实际上是获取当前对象的field字段的值。
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
实际的去重是通过TreeSet来实现的,外部的其他操作本质上是遍历传参,创建TreeSet并指定比较器,最后收集结果集。
验证可用性:
import java.util.*;
import java.util.stream.Collectors;
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age && Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void main(String[] args) {
User user=new User("藏三",18);
User user1=new User("藏三1",19);
User user2=new User("藏三2",28);
User user3=new User("藏三3",29);
User user4=new User("藏三4",18);
User user5=new User("藏三5",38);
User user6=new User("藏三6",48);
List<User> userList=new ArrayList<>();
userList.add(user);
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
userList.add(user5);
userList.add(user6);
userList.stream().forEach(System.out::println);
ArrayList<User> collect = userList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getAge))), ArrayList::new));
// //按照每十年一个年龄段,在各个年龄段里面要一个人
// ArrayList<User> collect = userList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o->{
// return o.getAge()/10;
// }))), ArrayList::new));
System.out.println("--------------------------");
collect.stream().forEach(System.out::println);
}
}
结果:(藏三4因为年龄和第一个一样,就被过滤掉了,并且数据也按照age进行了排序,升序)
注解掉代码的执行结果:(符合去重逻辑,每个年龄段只有一个人)
另外,HashSet不太适合用来做自定义去重,因为HashSet的去重是通过类的equals和hashCode方法实现的。