1. 導入:なぜpeekが必要なのか
JavaのStream APIは、宣言的で非常に強力ですが、複雑なパイプライン処理を書いていると「途中でどんなデータが流れているのか」を確認するのが難しいという課題があります。デバッグのためにいちいちforEachで出力してはリストを作り直す……そんな経験はありませんか?
ここで役立つのが peekメソッド です。これはストリームの処理を中断することなく、中間の状態をのぞき見(peek)できるため、開発中のデバッグやログ出力に最適なツールとなります。
2. 基礎知識:peekの仕組み
peekメソッドは、ストリームの各要素に対して指定したConsumerアクションを実行し、元のストリームをそのまま返します。
重要な点は、peekが 中間操作(Intermediate Operation) であるということです。末端操作(collectやforEachなど)が呼び出されない限り、peek内の処理は実行されません。この特性により、パイプラインの途中に差し込むだけで、処理フローを汚さずにデバッグが可能です。
3. 実装・解決策
peekを効果的に使うコツは、「状態の変更を行わない」ことです。あくまで「デバッグ・観測用」と割り切り、ラムダ式の中で値を書き換えるような処理は避けましょう。
主な用途は以下の通りです。
・フィルター後の要素数の確認
・map変換前後の値の確認
・並列ストリーム処理の実行スレッドの確認
4. サンプルプログラム
以下のコードは、リストのフィルタリングとマッピングの過程をpeekで可視化する例です。
import java.util.List;
import java.util.stream.Collectors;
public class PeekSample {
public static void main(String[] args) {
List
List
// フィルタリング前の状態を確認
.peek(name -> System.out.println(“フィルタリング前: ” + name))
.filter(name -> name.startsWith(“Java”))
// 変換後の状態を確認
.peek(name -> System.out.println(“フィルタリング後: ” + name))
.map(String::toUpperCase)
// 最終結果を確認
.peek(name -> System.out.println(“変換後: ” + name))
.collect(Collectors.toList());
}
}
5. 応用・注意点:現場での鉄則
現場で活用する際の注意点を3つ挙げます。
1. 副作用を入れない: peekの中でListへの追加や変数の書き換えを行うと、デバッグ用のコードがバグの温床になります。あくまで出力(System.outやlogger)に留めてください。
2. 遅延評価の罠: 前述の通り、末端操作が呼ばれないとpeekは実行されません。デバッグで何も表示されない場合は、ストリームが正しく終了しているか確認してください。
3. 本番環境での削除: peekは開発効率を劇的に上げますが、本番環境で大量のログを出力するとパフォーマンス低下を招きます。リリース時にはコードから削除するか、デバッグフラグで制御できるような構造にしましょう。
Sequenced Collectionsなど、Javaの新しいコレクションAPIと組み合わせる際も、peekを使えば複雑な加工処理の可読性を保ちつつ安全なデバッグが可能です。ぜひ明日の開発から取り入れてみてください。

コメント