首页 > 解决方案 > 如何在 Java 中的 Stream 中查找重复元素

问题描述

我正在尝试在地图值中查找重复条目。但问题是值列表具有多个属性/属性。基本上,如果一个标题在数据库中多次出现,我会将一个条目标记为唯一条目,并将其余条目标记为重复条目。

这是我当前的代码:

// I have a Map that looks like...

host1 : id | title | host1 | url | state | duplicate
        id | title | host1 | url | state | duplicate

host2 : id | title | host2 | url | state | duplicate
        id | title | host2 | url | state | duplicate


    for (Map.Entry<String, List<Record>> e : recordsByHost.entrySet()) {
      boolean executed = false;
      for (Record r : e.getValue()) {
        int frequency = Collections.frequency(
          e
            .getValue()
            .stream()
            .map(Record::getTitle)
            .collect(Collectors.toList()),
          r.getTitle()
        );
        if ((frequency > 1) && (!executed)) {
          markDuplicates(r.getId(), r.getTitle());
          executed = true;
        } else {
          executed = false;
        }

问题是当频率大于 2(具有相同标题的三个记录)时,该行评估为 false 并将第三个记录/第二个重复视为“唯一”。

我一直在尝试修改我的逻辑,但我担心我被卡住了。任何让我摆脱困境的帮助/建议将不胜感激。

标签: java

解决方案


当且仅当该值实际添加到 Set 时, Set.add(实际上是 Collection.add)才返回 true。由于 Set 始终强制唯一性,因此您可以使用它来查找重复项:

void markDuplicates(Iterable<? extends Record> records) {
    Set<String> foundTitles = new HashSet<>();

    for (Record r : records) {
        String title = r.getTitle();
        if (title != null && !foundTitles.add(title)) {
            // title was not added, because it's already been found.
            markAsDuplicate(r);
        }
    }
}

推荐阅读