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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 16:25:14  来源:igfitidea点击:

Java contains vs anyMatch behaviour

javajava-streamequality

提问by Tranquility

So if I have a Nameobject and have an ArrayListof type Name(names), and I want to ascertain whether my list of names contains a given Nameobject (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 trueif 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 anyMatchas 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 nullelements, then the predicate will throw a NullPointerExceptionwhen it tries to call equalson this nullobject.

基于流的版本的问题在于,如果集合(以及它的流)包含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 containsapproach was mentioned in the comments and in the other answer, and that may be worth mentioning here: If the type of the namescollection 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 nullarguments.

如果 n 为空,实际上并不重要,因为通常equals()方法知道null参数。