Java contains vs anyMatch 行为
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35200250/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java contains vs anyMatch behaviour
提问by Tranquility
So if I have a Name
object and have an ArrayList
of type Name
(names
), and I want to ascertain whether my list of names contains a given Name
object (n
), I could do it two ways:
因此,如果我有一个Name
对象并且有一个ArrayList
类型Name
( names
),并且我想确定我的名称列表是否包含给定的Name
对象 ( n
),我可以通过两种方式做到这一点:
boolean exists = names.contains(n);
or
或者
boolean exists - names.stream().anyMatch(x -> x.equals(n));
I was considering if these two would behave the same and then thought about what happens if n was assigned null
?
我在考虑这两个是否会表现相同,然后考虑如果分配 n 会发生什么null
?
For contains, as I understand, if the argument is null
, then it returns true
if the list contains null
. How would I achieve this anyMatch
- would it be by using Objects.equals(x, n)
?
对于包含,据我所知,如果参数是null
,那么它返回true
如果列表包含null
。我将如何实现这一目标anyMatch
- 是通过使用Objects.equals(x, n)
吗?
If that works, then which approach is more efficient - is it anyMatch
as it can take advantage of laziness and parallelism?
如果可行,那么哪种方法更有效 - 是否anyMatch
可以利用惰性和并行性?
采纳答案by Marco13
The problem with the stream-based version is that ifthe collection (and thus its stream) contains null
elements, then the predicate will throw a NullPointerException
when it tries to call equals
on this null
object.
基于流的版本的问题在于,如果集合(以及它的流)包含null
元素,那么NullPointerException
当它试图调用equals
这个null
对象时,谓词将抛出 a 。
This could be avoided with
这可以避免
boolean exists = names.stream().anyMatch(x -> Objects.equals(x, n));
But there is no practical advantage to be expected for the stream-based solution in this case. Parallelism might bring an advantage for reallylarge lists, but one should not casually throw in some parallel()
here and there assuming that it maymake things faster. First, you should clearly identify the actual bottlenecks.
但在这种情况下,基于流的解决方案没有预期的实际优势。并行性可能会为非常大的列表带来优势,但人们不应parallel()
假设它可以使事情变得更快,就随意地在这里和那里扔一些东西。首先,您应该清楚地确定实际瓶颈。
And in terms of readability, I'd prefer the first, classical solution here. If you want to check whether the list of names.contains(aParticularValue)
, you should do this - it just reads like prose and makes the intent clear.
就可读性而言,我更喜欢这里的第一个经典解决方案。如果你想检查 的列表names.contains(aParticularValue)
,你应该这样做 - 它只是读起来像散文并且使意图清晰。
EDIT
编辑
Another advantage of the contains
approach was mentioned in the comments and in the other answer, and that may be worth mentioning here: If the type of the names
collection is later changed, for example, to be a HashSet
, then you'll get the faster contains
-check (with O(1) instead of O(n)) for free - without changing any other part of the code. The stream-based solution would then still have to iterate over allelements, and this could have a significantly lower performance.
contains
评论和其他答案中提到了该方法的另一个优点,这里可能值得一提:如果names
集合的类型稍后更改,例如更改为 a HashSet
,那么您将获得更快的contains
-check (使用 O(1) 而不是 O(n))免费 - 无需更改代码的任何其他部分。然后,基于流的解决方案仍然必须迭代所有元素,这可能会显着降低性能。
回答by Zbynek Vyskovsky - kvr000
They should provide the same result if hashCode()
and equals()
are written in reasonable way.
如果hashCode()
和equals()
以合理的方式编写,它们应该提供相同的结果。
But the performance may be completely different. For Lists it wouldn't matter that much but for HashSet contains()
will use hashCode()
to locate the element and it will be done (most probably) in constant time. While with the second solution it will loop over all items and call a function so will be done in linear time.
但性能可能完全不同。对于列表,它没有那么重要,但是对于 HashSetcontains()
将用于hashCode()
定位元素,并且它将(最有可能)在恒定时间内完成。使用第二种解决方案时,它将遍历所有项目并调用函数,因此将在线性时间内完成。
If n is null, actually doesn't matter as usually equals()
methods are aware of null
arguments.
如果 n 为空,实际上并不重要,因为通常equals()
方法知道null
参数。