List列表运用Java8的stream流按某字段去重

更新时间:2023-07-11 20:01:12 阅读: 评论:0

List列表运⽤Java8的stream流按某字段去重
问题
项⽬中经常会遇到列表去重的问题,⼀般可使⽤Java8的stream()流提供的distinct()⽅法:list.stream().distinct()。
list的类型为List<String>、List<Integer>,list⾥的元素为简单包装类型。
或者List<Xxx>,其中Xxx为⾃定义对象类型,重写equals和hashCode⽅法,可根据业务情况来实现,如id相同即认为对象相等。
有时会遇到这种情况,需要对按对象⾥的某字段来去重。
例如:
@NoArgsConstructor
@AllArgsConstructor
@Data
class Book {
public static Book of(Long id, String name, String createTime) {
return new Book(id, name, Date.from(LocalDateTime.par(createTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).atZone(ZoneId.systemDefault()).toInstant()));
}
private Long id;
private String name;
private Date createTime;
}
现在我们要按name字段来去重,假设list如下:
求学路List<Book> books = new ArrayList<>();
books.add(Book.of(1L, "Thinking in Java", "2021-06-29 17:13:14"));
魔法师英文books.add(Book.of(2L, "Hibernate in action", "2021-06-29 18:13:14"));
books.add(Book.of(3L, "Thinking in Java", "2021-06-29 19:13:14"));
思路
1. 重写Book类的equals和hashCode⽅法,以name来判断⽐较是否相同,然后⽤stream的distinct⽅法来去重元宵节小作文
代码:
class Book {
...
@Override
public String toString() {
return String.format("(%s,%s,%s)", id, name, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").Instant().atZone(ZoneId.systemDefault()).toLocalDateTime()));    }
@Override
public boolean equals(Object o) {安全手抄报
if (this == o) return true;
构骨if (o == null || getClass() != o.getClass()) return fal;
Book book = (Book) o;
return Objects.equals(name, book.name);
}
}
商店用英语怎么说List<Book> distinctNameBooks1 = books.stream().distinct().List());
System.out.println(distinctNameBooks1);
总结:
通过重写equals和hashCode⽅法,按实际需求来⽐较,可直接使⽤stream的distinct⽅法去重,⽐较⽅便;
有时对象类不⽅便或者不能修改,如它已实现好或者是引⽤的三⽅包不能修改,该⽅法不能灵活地按字段来去重。
2. 通过llectingAndThen的Collection,⾥⾯⽤TreeSet在构造函数中指定字段
代码:
额状轴List<Book> distinctNameBooks2 = books.stream().Collection(() -> new TreeSet<>(paring(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.putIfAbnt(keyExtractor.apply(t), Boolean.TRUE) == null;
}
List<Book> distinctNameBooks3 = books.stream().filter(distinctByKey(o -> o.getName())).List());
System.out.println(distinctNameBooks3);
总结:
通过封装定义⼀个去重⽅法,配合filter⽅法可灵活的按字段去重,保持了原列表的顺序,不⾜之处是内部定义了⼀个HashMap,有⼀定内存占⽤,并且多了⼀个
⽅法定义。
4. 通过stream的filter⽅法来去重,不定义去重⽅法,在外⾯创建HashMap
代码:
Map<Object, Boolean> map = new HashMap<>();企业发展理念
List<Book> distinctNameBooks4 = books.stream().filter(i -> map.Name(), Boolean.TRUE) == null).List());
System.out.println(distinctNameBooks4);
总结:
仍然是配合filter⽅法实现去重,没有单独创建⽅法,临时定义⼀个HashMap,保持了原列表的顺序,不⾜之处是有⼀定内存占⽤。PS:暂时没找到stream流原⽣⽀持的可按某字段去重并且保持原列表顺序的⽅法
参考

本文发布于:2023-07-11 20:01:12,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1091301.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

下一篇:SQL rver去重
标签:类型   实现   对象   保持   字段
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图