1. ホーム
  2. java

[解決済み] ラムダ式でstream().map(...)をデバッグするには?

2022-06-26 19:42:11

質問

私たちのプロジェクトでは、java 8に移行しており、その新機能をテストしています。

私のプロジェクトでは、Guavaの述語と関数を使って、いくつかのコレクションをフィルタリングし、変換しています。 Collections2.transformCollections2.filter .

この移行では、例えばguavaのコードをjava 8の変更に変更する必要があります。だから、私がやっている変更は、一種のものです。

List<Integer> naturals = Lists.newArrayList(1,2,3,4,5,6,7,8,9,10,11,12,13);

Function <Integer, Integer> duplicate = new Function<Integer, Integer>(){
    @Override
    public Integer apply(Integer n)
    {
        return n * 2;
    }
};

Collection result = Collections2.transform(naturals, duplicate);

に...

List<Integer> result2 = naturals.stream()
    .map(n -> n * 2)
    .collect(Collectors.toList());

guava を使用すると、各変換処理をデバッグできるので、コードのデバッグが非常に楽になります。しかし、私の懸念は、例えば、次のようなコードをどのようにデバッグするかということです。 .map(n -> n*2) .

デバッガを使うと、次のようなコードが表示されます。

@Hidden
@DontInline
/** Interpretively invoke this form on the given arguments. */
Object interpretWithArguments(Object... argumentValues) throws Throwable {
    if (TRACE_INTERPRETER)
        return interpretWithArgumentsTracing(argumentValues);
    checkInvocationCounter();
    assert(arityCheck(argumentValues));
    Object[] values = Arrays.copyOf(argumentValues, names.length);
    for (int i = argumentValues.length; i < values.length; i++) {
        values[i] = interpretName(names[i], values);
    }
    return (result < 0) ? null : values[result];
}

しかし、Guavaのようにコードをデバッグするのが簡単ではありません。 n * 2 変換を見つけることができませんでした。

この変換を見る方法、またはこのコードを簡単にデバッグする方法はありますか?

編集:私は別のコメントから答えを追加し、答えを投稿しました。

ありがとうございます。 Holger のコメントで私の質問に答えてくれたおかげで、ラムダブロックを持つアプローチによって変換プロセスを見ることができ、ラムダボディの中で何が起こったかをデバッグすることができました。

.map(
    n -> {
        Integer nr = n * 2;
        return nr;
    }
)

おかげさまで Stuart Marks のおかげで、メソッド参照を持つというアプローチは、変換処理をデバッグすることも可能にしました。

static int timesTwo(int n) {
    Integer result = n * 2;
    return result;
}
...
List<Integer> result2 = naturals.stream()
    .map(Java8Test::timesTwo)
    .collect(Collectors.toList());
...

おかげさまで Marlon Bernardes の回答で、私のEclipseが表示すべきものを表示しないことに気づき、peek()の使用により結果を表示することができました。

どのように解決するのですか?

EclipseやIntelliJ IDEAを使いながらラムダ式をデバッグするのは、通常、問題ないでしょう。ブレークポイントを設定し、ラムダ式全体を検査しないように注意してください (ラムダ本体のみを検査します)。

別のアプローチとして peek を使ってストリームの要素を検査することです。

List<Integer> naturals = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13);
naturals.stream()
    .map(n -> n * 2)
    .peek(System.out::println)
    .collect(Collectors.toList());

UPDATEです。

あなたが混乱しているのは mapintermediate operation - の後にのみ実行される遅延操作です。 terminal operation が実行された後にのみ実行される遅延操作である。ですから、あなたが stream.map(n -> n * 2) を呼び出したとき、ラムダ本体は現時点では実行されていないのです。ブレークポイントを設定し、端末操作が呼ばれた後に検査する必要があります ( collect が呼ばれた後、ブレークポイントを設定して検査する必要があります(この場合)。

確認 ストリーム操作 を参照してください。

UPDATE 2:

引用元 ホルガーの のコメントを引用しています。

<ブロッククオート

ここで厄介なのは、mapの呼び出しとラムダ式が1つの行にあることです。 式が 1 行に存在するため、ブレークポイントが 2 つの全く関連性のない動作で停止してしまうことです。 で止まってしまうことです。

の直後に改行を挿入すると map( の直後に改行を入れると、ラムダ式だけのブレークポイントを設定することができます。 また、デバッガが中間値を表示しないのは珍しいことではなく a return 文の中間値を表示しないことも珍しくありません。ラムダを変更することで n -> { int result=n * 2; return result; } に変更すると、結果を検査することができます。ここでも改行が必要です。 行ごとにステップする場合は適切に改行すること...