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

新手上路,请多包涵

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

我的想法是这样的:

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

这是最好的方法吗?

原文由 pedrorijo91 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

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

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 重写,它也是短路的(对于不满足提供条件的第一个元素立即返回 false)

(假设非并行流和线程安全环境)

 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);
}

原文由 Pshemo 发布,翻译遵循 CC BY-SA 4.0 许可协议

我使用了以下内容:

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 评论 里说。

原文由 Sasha 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题