How to debug stream().map(…) with lambda expressions?

前端 未结 6 1762
一向
一向 2020-12-02 05:28

In our project we are migrating to java 8 and we are testing the new features of it.

On my project I\'m using Guava predicates and functions to filter and transform

6条回答
  •  爱一瞬间的悲伤
    2020-12-02 06:00

    Debugging lambdas also works well with NetBeans. I'm using NetBeans 8 and JDK 8u5.

    If you set a breakpoint on a line where there's a lambda, you actually will hit once when the pipeline is set up, and then once for each stream element. Using your example, the first time you hit the breakpoint will be the map() call that's setting up the stream pipeline:

    first breakpoint

    You can see the call stack and the local variables and parameter values for main as you'd expect. If you continue stepping, the "same" breakpoint is hit again, except this time it's within the call to the lambda:

    enter image description here

    Note that this time the call stack is deep within the streams machinery, and the local variables are the locals of the lambda itself, not the enclosing main method. (I've changed the values in the naturals list to make this clear.)

    As Marlon Bernardes pointed out (+1), you can use peek to inspect values as they go by in the pipeline. Be careful though if you're using this from a parallel stream. The values can be printed in an unpredictable order across different threads. If you're storing values in a debugging data structure from peek, that data structure will of course have to be thread-safe.

    Finally, if you're doing a lot of debugging of lambdas (especially multi-line statement lambdas), it might be preferable to extract the lambda into a named method and then refer to it using a method reference. For example,

    static int timesTwo(int n) {
        return n * 2;
    }
    
    public static void main(String[] args) {
        List naturals = Arrays.asList(3247,92837,123);
        List result =
            naturals.stream()
                .map(DebugLambda::timesTwo)
                .collect(toList());
    }
    

    This might make it easier to see what's going on while you're debugging. In addition, extracting methods this way makes it easier to unit test. If your lambda is so complicated that you need to be single-stepping through it, you probably want to have a bunch of unit tests for it anyway.

提交回复
热议问题