Java - ラムダ式を使用してストリームをフィルタリングする PlatoBlockchain Data Intelligence。垂直検索。あい。

Java – ラムダ式でストリームをフィルタリングする

Java Streams は、冗長な Java を関数型プログラミング パラダイムに導入するために、8 年の Java 2014 で導入されました。 Java Streams は、コレクション処理をワンライナーで実行するための柔軟で強力な関数操作を多数公開しています。

いくつかの述語に基づくコレクションのフィルタリングは、依然として最も一般的に使用される関数操作の XNUMX つであり、 Predicate またはもっと簡潔に – と ラムダ式.

この短いガイドでは、ラムダ式を使用して Java 8 ストリームをフィルタリングする方法を見ていきます。

Java でのストリームのフィルタリング

一般的に、 Stream 経由でフィルタリングできます filter() メソッド、および指定された述語:

Stream filter(Predicate<? super T> predicate)

ストリーム内の各要素は述語に対して実行され、述語が返された場合に出力ストリームに追加されます true. あなたが提供することができます Predicate インスタンス:

Predicate contains = s -> s.contains("_deprecated");
List results = stream.filter(contains).collect(Collectors.toList());

または、ラムダ式を提供して単純化します。

List results = stream.filter(s -> s.contains("_deprecated"))
                             .collect(Collectors.toList());

または、ラムダ式を メソッドリファレンス:


List results = stream.filter(String::isEmpty)
                             .collect(Collectors.toList());

メソッド参照では、引数を渡すことはできませんが、フィルタリングしているオブジェクトでメソッドを定義し、簡単にフィルタリングできるように調整できます (メソッドが引数を受け入れず、 boolean).

ことを忘れないでください ストリームはコレクションではありません – それらはストリームです コレクションの、およびそれらを収集して、などのコレクションに戻す必要があります List, Mapなど、それらに永続性を与えます。 さらに、ストリーム要素に対して行われるすべての操作は、 中間の or ターミナル:

  • 中間操作は、前の操作からの変更を含む新しいストリームを返します
  • ターミナル操作はデータ型を返し、ストリームでの処理のパイプラインを終了することを意図しています

filter() あります 中間の ストリームが終了する前に、他の中間操作と連鎖することを意図しています。 変更 (要素自体の変更やフィルター処理された結果など) を永続化するには、結果を割り当てる必要があります。 出力ストリーム 端末操作を介して、新しい参照変数に。

注: 多くのラムダ式をチェーンする場合でも、適切な改行を使用すると、読みやすさの問題に遭遇しない場合があります。

次の例では、この書籍のリストを使用します。

Book book1 = new Book("001", "Our Mathematical Universe", "Max Tegmark", 432, 2014);
Book book2 = new Book("002", "Life 3.0", "Max Tegmark", 280, 2017);
Book book3 = new Book("003", "Sapiens", "Yuval Noah Harari", 443, 2011);
        
List books = Arrays.asList(book1, book2, book3);

Stream.filter() を使用してコレクションをフィルター処理する

この本のコレクションをフィルタリングしてみましょう。 どのような述語でも構いません。たとえば、400 ページを超える書籍をフィルターしてみましょう。

List results = books.stream()
                          .filter(b -> b.getPageNumber() > 400)
                          .collect(Collectors.toList());

これにより、以下を含むリストが得られます。

[
Book{id='001', name='Our Mathematical Universe', author='Max Tegmark', pageNumber=432, publishedYear=2014}, 
Book{id='003', name='Sapiens', author='Yuval Noah Harari', pageNumber=443, publishedYear=2011}
]

フィルタリングするとき、連鎖するための本当に便利な方法は map()これにより、オブジェクトを別の値にマップできます。 たとえば、各本をその名前にマップして、 からの述語に適合する本の filter() コール:

List results = books.stream()
                            .filter(b -> b.getPageNumber() > 400)
                            .map(Book::getName)
                            .collect(Collectors.toList());

これにより、文字列のリストが得られます。

[Our Mathematical Universe, Sapiens]

Stream.filter() を使用して複数の述語でコレクションをフィルター処理する

通常、複数の基準でコレクションをフィルタリングしたいと考えています。 これは、複数の連鎖によって行うことができます filter() 呼び出し or XNUMX つの条件で XNUMX つの条件をチェックする短絡述語を使用する filter() コール。

 List results = books.stream()
                    .filter(b -> b.getPageNumber() > 400 && b.getName().length() > 10)
                    .collect(Collectors.toList());
                    


 List results2 = books.stream()
                    .filter(b -> b.getPageNumber() > 400)
                    .filter(b -> b.getName().length() > 10)
                    .collect(Collectors.toList());

ベストプラクティス、業界で認められた標準、および含まれているチートシートを含む、Gitを学習するための実践的で実用的なガイドを確認してください。 グーグルGitコマンドを停止し、実際に 学ぶ それ!

複数の基準を利用する場合 – ラムダ呼び出しは多少長くなる可能性があります。 この時点で、それらをスタンドアロンの述語として抽出すると、より明確になる可能性があります。 しかし、どちらのアプローチがより高速ですか?

複雑な条件を持つ単一のフィルターまたは複数のフィルター?

ハードウェア、コレクションの大きさ、および並列ストリームを使用するかどうかによって異なります。 一般に、複雑な条件を持つ XNUMX つのフィルターは、より単純な条件 (小規模から中規模のコレクション) を持つ複数のフィルターよりもパフォーマンスが優れているか、同じレベルで実行されます (非常に大規模なコレクション)。 条件が長すぎる場合 – 複数の条件に分散することでメリットが得られる場合があります filter() パフォーマンスが非常に似ているため、読みやすさを向上させるために呼び出します。

最良の選択は、両方を試すことです。 対象機器、それに応じて戦略を調整します。

GitHub ユーザー ヴォルコダフ スループット操作/秒でフィルタリング ベンチマークを実行し、結果を 「javafilters-ベンチマーク」 リポジトリ。 結果は有益な表にまとめられています。

コレクションのサイズが大きくなると、収益が明らかに減少し、どちらのアプローチもほぼ同じレベルで実行されます。 並列ストリームはコレクションのサイズが大きいほど大きなメリットがありますが、サイズが小さい (要素が 10 以下) とパフォーマンスが低下します。 並列ストリームは、非並列ストリームよりもはるかに優れたスループットを維持し、入力に対する堅牢性が大幅に向上したことに注意してください。

タイムスタンプ:

より多くの スタックアバス