Java 包含 vs anyMatch 行为

标签 java java-stream equality

所以如果我有一个 Name 对象并且有一个 Name (names) 类型的 ArrayList,并且我想确定我的姓名列表是否包含给定的 Name 对象 (n),我可以通过两种方式进行:

boolean exists = names.contains(n);

boolean exists = names.stream().anyMatch(x -> x.equals(n));

我正在考虑这两个是否会表现相同,然后考虑如果将 n 分配为 null 会发生什么?

据我了解,如果参数为 null,则如果列表包含 null,则返回 true。我将如何实现这个 anyMatch - 是通过使用 Objects.equals(x, n) 吗?

如果它是这样工作的,那么哪种方法更有效 - 它是 anyMatch 因为它可以利用惰性和并行性?

最佳答案

基于流的版本的问题是 if 集合(以及它的流)包含 null 元素,那么谓词将抛出 NullPointerException 当它试图在这个 null 对象上调用 equals 时。

这可以避免

boolean exists = names.stream().anyMatch(x -> Objects.equals(x, n));

但在这种情况下,基于流的解决方案没有任何实际优势。并行性可能会为 真正 大型列表带来优势,但不应该随便在各处添加一些 parallel() 假设它可能事情更快。首先,您应该清楚地确定实际的瓶颈。

就可读性而言,我更喜欢这里的第一个经典解决方案。如果你想检查 names.contains(aParticularValue) 的列表是否,你应该这样做——它读起来像散文,意图清晰。

EDIT

在评论和其他答案中提到了 contains 方法的另一个优点,在这里可能值得一提:如果 names 集合的类型是稍后更改为 HashSet,然后您将免费获得更快的 contains-check(使用 O(1) 而不是 O(n)) - 无需更改代码的任何其他部分。然后,基于流的解决方案仍然必须遍历 所有 元素,这可能会显着降低性能。

关于Java 包含 vs anyMatch 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35200250/

相关文章:

java - Reduce 为并行流返回不可预测的结果

objective-c - 对于具有两个字符串和两个 BOOL 的对象,什么是好的散列?

c# - Java 和 .NET 3.5 之间进程间通信的最佳方法是什么?

java - 确保调用的方法在 Spring @Transactional 边界内

java - 读取目标/测试类上的文件 FileNotFound

c# - "(float)integer == integer"在 C# 中是否保证相等?

ruby - 重写 Ruby 中的 == 运算符

java - Solr SearchComponent 获取所有文档

java - 创建 Stream 后更改 Stream 源时 Stream 的行为

Java 流 API。在一行中查找对象匹配谓词的字段。如果不存在则返回一些默认值