所以如果我有一个 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/