如何使用lambda计算对象字段中的重复?

时间:2017-04-25 10:31:43

标签: java lambda

我有图书清单。

final List<Book> books = new ArrayList<>();
books.add(new Book(50, "Book1", 1997));
books.add(new Book(110, "Book2", 1998));
books.add(new Book(150, "Book3", 1999));
books.add(new Book(200, "Book4", 2000));
books.add(new Book(250, "Book1", 2001));

我试图按标题计算重复数。

final Integer countDuplicates = books.stream()
    .filter(b -> Collections.frequency(books, b.getTitle()) > 1)
    .collect(Collectors.toList()).size();

但它不起作用。请帮帮我。

3 个答案:

答案 0 :(得分:2)

您遇到的问题是b.getTitle()不是您在列表中保留的对象。您持有Book而不是其标题。此外,您可能没有实现Book,因此它与String相当(可以)。

你能做什么,取决于你最感兴趣的东西。这是一个示例,其中包含所有标题以及列表中包含该标题的书籍数量:

Map<String, Long> duplicatesPerTitle = 
                          books.stream()
                               .collect(Collectors.groupingBy(Book::getTitle, 
                                                              Collectors.counting()));
System.out.println("duplicatesPerTitle = " + duplicatesPerTitle);

只对大于1的数字感兴趣?从这里你也可以使用以下内容:

duplicatesPerTitle.entrySet().stream()
                             .filter(e -> e.getValue() > 1)
                             .forEach(System.out::println);

答案 1 :(得分:1)

你错误地使用frequency方法 - 你需要传递一系列书籍并寻找一本书或一组字符串并寻找一个字符串 - 但此刻你传递了一系列书籍并寻找一个字符串 - 所以它总是返回0。

一种方法是:

Map<String, Long> frequency = books.stream()
    .map(Book::getTitle)
    .collect(Collectors.groupingBy(s -> s, Collectors.counting()));

返回一个地图,其中键是标题,值是频率。

如果要计算重复项,可以执行以下操作:

long duplicates = frequency.values().stream().filter(f -> f >= 2).count();

答案 2 :(得分:0)

构造一个集合,然后从集合中减去列表的大小。确保使用适当的比较器来检测重复项。