如何检查 Java 8 个流中是否存在重复项?

How to check if exists any duplicate in Java 8 Streams?

在 java 8 中,检查列表是否包含重复项的最佳方法是什么?

我的想法是这样的:

list.size() != list.stream().distinct().count()

这是最好的方法吗?

您的代码需要遍历所有元素。如果你想确保没有重复的简单方法,比如

public static <T> boolean areAllUnique(List<T> list){
    Set<T> set = new HashSet<>();

    for (T t: list){
        if (!set.add(t))
            return false;
    }

    return true;
}

会更有效率,因为它可以在找到第一个非唯一元素时立即给你 false

这个方法也可以重写为(假设非并行流和线程安全环境)使用 Stream#allMatch 这也是短路的(returns false 立即为第一个元素不' t 满足提供的条件)

public static <T> boolean areAllUnique(List<T> list){
    Set<T> set = new HashSet<>();
    return list.stream().allMatch(t -> set.add(t));
}

或评论

中提到的@Holger
public static <T> boolean areAllUnique(List<T> list){
    return list.stream().allMatch(new HashSet<>()::add);
}

开始这个 class 作为 StreamTool,但我认为必须有更好的方法使用 reduce 或类似的:

public class StreamTool {

    /**
     * Whether stream records are unique in that stream.
     * @param <T> Type of records
     * @param records
     * @return true if there are no duplicates, false otherwise
     */
    public static <T> boolean isUnique(Stream<T> records) {
        return records.allMatch(new HashSet<>()::add);
    }
}

我使用了以下内容:
1. return list.size() == new HashSet<>(list).size();.

我不确定它与以下相比如何:
2. return list.size() == list.stream().distinct().count();

3.return list.stream().sequential().allMatch(new HashSet<>()::add);
在性能方面。

最后一个 (#3) 不仅可以处理集合(例如列表),还可以处理流(无需显式收集它们)。

更新:最后一个 (#3) 似乎是最好的,不仅因为它可以处理纯流,而且因为它在第一个重复项上停止(而 #1 和 #2 总是迭代到最后) — 正如@Pshemo 在 comment 中所说的那样。

您可以使用计数收集器。

Stream.of(1, 3, 4, 6, 7, 5, 6)
            .collect(Collectors.groupingBy(
                    Function.identity(), Collectors.counting()))
            .entrySet().stream().anyMatch(e -> e.getValue() > 1)

给定数组arr,

arr.length != Arrays.stream(arr).distinct().count()

将有助于检查重复项

使用set.add()速度更快

Set<T> items = new HashSet<>();
list.stream().filter(n -> !items.add(n)) 
            .collect(Collectors.toSet());