Java 8 根据属性值对列表去重
对列表的去重处理,Java 8 在 Stream 接口上提供了类似于 SQL 语句那样的 distinct() 方法,不过它也只能基于对象整体比较来去重,即通过 equals/hashCode 方法。distinct 方法的功效与以往的 new ArrayList(new HashSet(books)) 差不多。用起来是
List<Book> unique = book.stream().distinct().collect(Collectors.toList())
并且这种去重方式需要在模型类中同时实现 equals 和 hashCode 方法。
回到实际项目中来,我们很多时候的需求是要根据对象的某个属性来去重。比如接下来的一个实例,一个 books 列表中存在 ID 一样,name 却不同的 book, 我们认为这是重复的,所以需要根据 book 的 id 属性对行去重。在 collect 的时候用到的方法是 collectinAndThen(...), 下面是简单代码:
1import java.util.*;
2
3import static java.util.stream.Collectors.collectingAndThen;
4import static java.util.stream.Collectors.toCollection;
5
6
7public class Deduplication {
8
9 public static void main(String[] args) {
10
11 List<Book> books = Arrays.asList(
12 new Book(12, "Sun Java"),
13 new Book(12, "Oracle Java"),
14 new Book(15, "Scala")
15 );
16
17 List<Book> unique = books.stream().collect(
18 collectingAndThen(toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.id))),
19 ArrayList::new));
20
21 unique.forEach(book -> System.out.printf("book[id: %s, name: %s]\n", book.id, book.name));
22 }
23}
24
25class Book {
26 public final Integer id;
27 public final String name;
28
29 public Book(Integer id, String name) {
30 this.id = id;
31 this.name = name;
32 }
33}执行后打印出
book[id: 12, name: Sun Java]
book[id: 15, name: Scala]
成功去重,换个名照样能认出来,还不依赖于 equals/hashCode 方法。
链接: Remove duplicates from a list of objects based on property in Java 8
永久链接 https://yanbin.blog/java-8-list-deduplication-with-lambda/, 来自 隔叶黄莺 Yanbin's Blog[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。