1. 序章

Java Stream API は、データを処理するための強力な代替手段を紹介します。

この短いチュートリアルでは、よく誤解されるメソッドである peek()に焦点を当てます。

2. 簡単な例

手を汚してpeek()を使ってみましょう。 名前のストリームがあり、それらをコンソールに出力したいと思います。

以来ピーク() を期待します消費者その唯一の議論として、それはぴったりのように思われるので、試してみましょう:

Stream<String> nameStream = Stream.of("Alice", "Bob", "Chuck");
nameStream.peek(System.out::println);

ただし、上記のスニペットは出力を生成しません。 その理由を理解するために、ストリームのライフサイクルの側面について簡単に復習しましょう。

3. 中級vs。 ターミナルオペレーション

ストリームには、データソース、0個以上の中間操作、および0個または1個の端末操作の3つの部分があることを思い出してください。

ソースは要素をパイプラインに提供します。

中間操作では、要素を1つずつ取得して処理します。 すべての中間操作は遅延であり、その結果、パイプラインが機能し始めるまで操作は効果がありません。

ターミナル操作は、ストリームのライフサイクルの終わりを意味します。 このシナリオで最も重要なのは、パイプラインで作業を開始することです。

4. peek()使用法

最初の例でpeek()が機能しなかった理由は、は中間操作であり、パイプラインにターミナル操作を適用しなかったためです。 または、 forEach()を同じ引数で使用して、目的の動作を取得することもできます。

Stream<String> nameStream = Stream.of("Alice", "Bob", "Chuck");
nameStream.forEach(System.out::println);

peek() Javadocページは次のように述べています。「このメソッドは主にデバッグをサポートするために存在し、要素がパイプラインの特定のポイントを通過するときに要素を確認する必要があります。 」。

同じJavadocページからのこのスニペットを考えてみましょう。

Stream.of("one", "two", "three", "four")
  .filter(e -> e.length() > 3)
  .peek(e -> System.out.println("Filtered value: " + e))
  .map(String::toUpperCase)
  .peek(e -> System.out.println("Mapped value: " + e))
  .collect(Collectors.toList());

これは、各操作を通過した要素をどのように観察するかを示しています。

さらに、 peek()は、別のシナリオで役立ちます。要素の内部状態を変更する場合。 たとえば、すべてのユーザーの名前を印刷する前に小文字に変換するとします。

Stream<User> userStream = Stream.of(new User("Alice"), new User("Bob"), new User("Chuck"));
userStream.peek(u -> u.setName(u.getName().toLowerCase()))
  .forEach(System.out::println);

または、 map()を使用することもできますが、要素を置き換えたくないので、 peek()の方が便利です。

5. 結論

この短いチュートリアルでは、 peek()がどのように機能するかを理解するために、ストリームのライフサイクルの概要を確認しました。 また、 peek()を使用することが最も簡単なオプションである場合、2つの日常的なユースケースを見ました。

そしていつものように、例はGitHub利用できます。