1.重写Info
类的equals
和hashCode
方法,以recordNum
来判断比较是否相同,然后用stream的distinct方法来去重
public class Info extends BaseEntity {
...
...
private String recordNum;
...
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Info info = (Info) o;
return Objects.equals(recordNum, info.recordNum);
}
}
//去重
List<Info> distinctInfos= infos.stream().distinct().collect(Collectors.toList());
总结:
通过重写equals
方法,按实际需求来比较,直接使用stream的distinct方法去重,比较方便;
有时对象类不方便或者不能修改,如它已实现好或者是引用的三方包不能修改,该方法不能灵活地按字段来去重。
2. 通过Collectors.collectingAndThen
的Collectors.toCollection
,里面用TreeSet
在构造函数中指定字段
List<Book> distinctNameBooks2 = books.stream()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(
Comparator.comparing(o -> o.getName()))), ArrayList::new));
System.out.println(distinctNameBooks2);
总结:
使用stream流提供的方法,代码很简洁,但不足是虽然实现了去重效果,但list里的顺序变化了,而有的场景需要保持顺序。
3.通过stream的filter
方法来去重,定义一个去重方法,参数为Function
类型,返回值为Predicate
类型
public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Map<Object, Boolean> map = new HashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
List<Book> distinctNameBooks3 = books.stream().filter(distinctByKey(o -> o.getName())).collect(Collectors.toList());
System.out.println(distinctNameBooks3);
总结:
通过封装定义一个去重方法,配合filter
方法可灵活的按字段去重,保持了原列表的顺序,不足之处是内部定义了一个HashMap
,有一定内存占用,并且多了一个方法定义。
4.通过stream的filter
方法来去重,不定义去重方法,在外面创建HashMap
Map<Object, Boolean> map = new HashMap<>();
List<Book> distinctNameBooks4 = books.stream().filter(i -> map.putIfAbsent(i.getName(), Boolean.TRUE) == null).collect(Collectors.toList());
System.out.println(distinctNameBooks4);
总结:
仍然是配合filter
方法实现去重,没有单独创建方法,临时定义一个HashMap
,保持了原列表的顺序,不足之处是有一定内存占用。