Java Stream 操作を分析する
Java ストリームはデバッグが難しい場合があります。 これは、Java ストリームがバックグラウンドで処理ロジックを処理するため、特定の値がどのように導出されるかのトレースが複雑になる可能性があるためです。 Java ストリームのデバッグを支援するために、IntelliJ IDEA は Java ストリーム内で何が起こっているかを視覚化します。
関数スタイルで書かれた簡単なプログラムを取り上げて、関数がどのように機能するかを示しましょう。
import java.util.stream.IntStream;
class PrimeFinder {
static int skip = 0;
static int limit = 100;
public static void main(String[] args) {
if (args.length >= 1) skip = Integer.parseInt(args[0]);
if (args.length >= 2) limit = Integer.parseInt(args[1]);
IntStream.iterate(1, n -> n + 1)
.skip(skip)
.limit(limit)
.filter(PrimeTest::isPrime)
.forEach(System.out::println);
}
}
class PrimeTest {
static boolean isPrime(int candidate) {
return candidate == 91 || // a bug here
IntStream.rangeClosed(2, (int) Math.sqrt(candidate))
.noneMatch(n -> (candidate % n == 0));
}
}
クラス名が示すように、このアプリは素数を見つけます。 プログラム引数を使用して、開始数とチェックする候補の数を指定できます。 チェックロジックは、Java 8 ストリームによって処理されます。
プログラムの出力を見ると、そこに余分な数字があります。
79
83
89
91 <- extra
97
これらの誤った数値がどこから来ているのかを理解するために、ストリームデバッガー機能を使用しましょう。
ストリームが使用されている行でプログラムを中断します。 これには、ターミナル操作を含む任意のストリーム操作を使用できます。
public static void main(String[] args) { if (args.length >= 1) skip = Integer.parseInt(args[0]); if (args.length >= 2) limit = Integer.parseInt(args[1]); IntStream.iterate(1, n -> n + 1) // set breakpoint here .skip(skip) .limit(limit) .filter(PrimeTest::isPrime) .forEach(System.out::println); }デバッグ ツールウィンドウのツールバーで、 詳細
をクリックし、 現在のストリームチェーンをトレース
を選択します。
ストリームトレース ダイアログを使用して、ストリーム内の操作を分析します。 上部のタブでは、特定の操作を切り替えて、各操作で値がどのように変換されるかを確認できます。

ストリームを調査すると、追加の値は filter 操作から来ていることがわかります。 バグの検索は、 filter の 述語 、より具体的には PrimeTest.isPrime() メソッドに絞り込まれました。
2026 年 3 月 30 日