web-dev-qa-db-ja.com

Java containsとanyMatchの動作

したがって、NameオブジェクトとArrayListName)型のnamesがあり、名前のリストにが含まれているかどうかを確認したい場合は、 Nameオブジェクト(n)が与えられた場合、2つの方法で実行できます。

_boolean exists = names.contains(n);
_

または

_boolean exists - names.stream().anyMatch(x -> x.equals(n));
_

これら2つが同じように振る舞うかどうかを考えていて、nがnullに割り当てられたらどうなるか考えましたか?

私が理解しているように、引数がnullである場合、リストにtrueが含まれている場合、nullを返します。これをどのように達成しますかanyMatch-Objects.equals(x, n)を使用することで実現できますか?

それが機能する場合、どのアプローチがより効率的です-それは怠[と並列性を利用できるのでanyMatchですか?

24
Tranquility

ストリームベースのバージョンの問題は、ifコレクション(したがってそのストリーム)にnull要素が含まれているため、述語がNullPointerExceptionをスローしようとすることです。このequalsオブジェクトでnullを呼び出します。

これは次の方法で回避できます

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

ただし、この場合、ストリームベースのソリューションに期待される実用的な利点はありません。並列処理はreally大きなリストに利点をもたらす可能性がありますが、mayを想定してあちこちでparallel()を偶然スローするべきではありません物事を高速化します。まず、実際のボトルネックを明確に特定する必要があります。

そして読みやすさの観点から、私はここで最初の古典的な解決策を好むでしょう。 names.contains(aParticularValue)のリストを確認したい場合は、これを行う必要があります-散文のように読み、意図を明確にします。

編集

containsアプローチの別の利点は、コメントと他の回答で言及されており、ここで言及する価値があるかもしれません:namesコレクションのタイプが後で変更された場合、たとえばHashSetにすると、contains- check(O(1)の代わりにO(n))で高速になります無料-コードの他の部分を変更することなく。その場合、ストリームベースのソリューションはall要素を繰り返し処理する必要があり、これによりパフォーマンスが大幅に低下する可能性があります。

24
Marco13

hashCode()equals()が合理的な方法で記述されている場合、それらは同じ結果を提供するはずです。

ただし、パフォーマンスは完全に異なる場合があります。リストの場合はそれほど重要ではありませんが、HashSetの場合、contains()hashCode()を使用して要素を特定し、(ほとんどの場合)一定の時間で実行されます。 2番目のソリューションでは、すべてのアイテムをループして関数を呼び出すため、線形時間で実行されます。

Nがnullの場合、通常equals()メソッドはnull引数を認識しているため、実際には問題ではありません。