Java 包含 vs anyMatch 行为
Java contains vs anyMatch behaviour
所以如果我有一个 Name
对象和一个类型为 Name
(names
) 的 ArrayList
,我想确定我的名字列表是否包含对于给定的 Name
对象 (n
),我可以通过两种方式实现:
boolean exists = names.contains(n);
或
boolean exists = names.stream().anyMatch(x -> x.equals(n));
我在考虑这两个行为是否相同,然后考虑如果分配 n 会发生什么情况 null
?
对于包含,据我了解,如果参数是 null
,那么它 returns true
如果列表包含 null
。我将如何实现这个 anyMatch
- 是通过使用 Objects.equals(x, n)
吗?
如果这是它的工作原理,那么哪种方法更有效 - anyMatch
是因为它可以利用惰性和并行性吗?
基于流的版本的问题是 如果 集合(及其流)包含 null
个元素,则谓词将抛出 NullPointerException
当它试图在此 null
对象上调用 equals
时。
这可以通过
来避免
boolean exists = names.stream().anyMatch(x -> Objects.equals(x, n));
但在这种情况下,基于流的解决方案没有实际优势。并行性可能会给 really 大列表带来优势,但不应该随意地在这里和那里扔一些 parallel()
假设它 可能 让事情变得更快。首先,你应该清楚地识别实际的瓶颈。
就可读性而言,我更喜欢这里的第一个经典解决方案。如果你想检查 names.contains(aParticularValue)
的列表,你应该这样做 - 它读起来像散文并且使意图明确。
EDIT
contains
方法的另一个优点在评论和其他答案中提到,这里可能值得一提:如果稍后更改 names
集合的类型,因为例如,要成为 HashSet
,那么您将免费获得更快的 contains
-check(使用 O(1) 而不是 O(n))——无需更改代码的任何其他部分。基于流的解决方案仍然必须遍历 all 元素,这可能会显着降低性能。
如果 hashCode()
和 equals()
写得合理,它们应该提供相同的结果。
但表现可能完全不同。对于 Lists 没那么重要,但是对于 HashSet contains()
将使用 hashCode()
来定位元素并且它会(很可能)在恒定时间内完成。而对于第二种解决方案,它将遍历所有项目并调用一个函数,因此将在线性时间内完成。
如果 n 为空,实际上并不重要,因为通常 equals()
方法知道 null
个参数。
所以如果我有一个 Name
对象和一个类型为 Name
(names
) 的 ArrayList
,我想确定我的名字列表是否包含对于给定的 Name
对象 (n
),我可以通过两种方式实现:
boolean exists = names.contains(n);
或
boolean exists = names.stream().anyMatch(x -> x.equals(n));
我在考虑这两个行为是否相同,然后考虑如果分配 n 会发生什么情况 null
?
对于包含,据我了解,如果参数是 null
,那么它 returns true
如果列表包含 null
。我将如何实现这个 anyMatch
- 是通过使用 Objects.equals(x, n)
吗?
如果这是它的工作原理,那么哪种方法更有效 - anyMatch
是因为它可以利用惰性和并行性吗?
基于流的版本的问题是 如果 集合(及其流)包含 null
个元素,则谓词将抛出 NullPointerException
当它试图在此 null
对象上调用 equals
时。
这可以通过
来避免boolean exists = names.stream().anyMatch(x -> Objects.equals(x, n));
但在这种情况下,基于流的解决方案没有实际优势。并行性可能会给 really 大列表带来优势,但不应该随意地在这里和那里扔一些 parallel()
假设它 可能 让事情变得更快。首先,你应该清楚地识别实际的瓶颈。
就可读性而言,我更喜欢这里的第一个经典解决方案。如果你想检查 names.contains(aParticularValue)
的列表,你应该这样做 - 它读起来像散文并且使意图明确。
EDIT
contains
方法的另一个优点在评论和其他答案中提到,这里可能值得一提:如果稍后更改 names
集合的类型,因为例如,要成为 HashSet
,那么您将免费获得更快的 contains
-check(使用 O(1) 而不是 O(n))——无需更改代码的任何其他部分。基于流的解决方案仍然必须遍历 all 元素,这可能会显着降低性能。
如果 hashCode()
和 equals()
写得合理,它们应该提供相同的结果。
但表现可能完全不同。对于 Lists 没那么重要,但是对于 HashSet contains()
将使用 hashCode()
来定位元素并且它会(很可能)在恒定时间内完成。而对于第二种解决方案,它将遍历所有项目并调用一个函数,因此将在线性时间内完成。
如果 n 为空,实际上并不重要,因为通常 equals()
方法知道 null
个参数。