如何使用 lambda 表达式调试 stream().map(...)? [英] How to debug stream().map(...) with lambda expressions?

查看:53
本文介绍了如何使用 lambda 表达式调试 stream().map(...)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我们的项目中,我们正在迁移到 Java 8 并测试它的新功能.

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

在我的项目中,我使用 Guava 谓词和函数来过滤和转换一些使用 Collections2.transformCollections2.filter 的集合.

On my project I'm using Guava predicates and functions to filter and transform some collections using Collections2.transform and Collections2.filter.

在这次迁移中,我需要将例如番石榴代码更改为 java 8 更改.所以,我正在做的改变是这样的:

On this migration I need to change for example guava code to java 8 changes. So, the changes I'm doing are the kind of:

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());

使用番石榴我很舒服地调试代码,因为我可以调试每个转换过程,但我关心的是如何调试例如.map(n -> n*2).

Using guava I was very confortable debugging the code since I could debug each transformation process but my concern is how to debug for example .map(n -> n*2).

使用调试器我可以看到一些代码,如:

Using the debugger I can see some code like:

@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转换.

But it isn't as straighforward as Guava to debug the code, actually I couldn't find the n * 2 transformation.

有什么办法可以看到这种转换,或者有办法轻松调试这段代码吗?

Is there a way to see this transformation or a way to easy debug this code?

我添加了来自不同评论的答案并发布了答案

感谢 Holger 评论回答了我的问题,使用 lambda 块的方法让我能够看到转换过程并调试 lambda 体内部发生的事情:

Thanks to Holger comment that answered my question, the approach of having lambda block allowed me to see the transformation process and debug what happened inside lambda body:

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

感谢 Stuart Marks 使用方法引用的方法也让我能够调试转换过程:

Thanks to Stuart Marks the approach of having method references also allowed me to debug the transformation process:

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() 的使用有助于显示结果.

Thanks to Marlon Bernardes answer I noticed that my Eclipse doesn't show what it should and the usage of peek() helped to display results.

推荐答案

我通常在使用 Eclipse 或 IntelliJ IDEA 时调试 lambda 表达式没有问题.只需设置一个断点,并确保不要检查整个 lambda 表达式(仅检查 lambda 主体).

I usually have no problem debugging lambda expressions while using Eclipse or IntelliJ IDEA. Just set a breakpoint and be sure not to inspect the whole lambda expression (inspect only the lambda body).

另一种方法是使用 peek 来检查流的元素:

Another approach is to use peek to inspect the elements of the stream:

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());

更新:

我认为你会感到困惑,因为 map 是一个 中间操作 - 换句话说:它是一个惰性操作,只会在 之后执行终端操作被执行.因此,当您调用 stream.map(n -> n * 2) 时,lambda 主体目前并未执行.您需要设置断点并在调用终端操作后对其进行检查(在本例中为 collect).

I think you're getting confused because map is an intermediate operation - in other words: it is a lazy operation which will be executed only after a terminal operation was executed. So when you call stream.map(n -> n * 2) the lambda body isn't being executed at the moment. You need to set a breakpoint and inspect it after a terminal operation was called (collect, in this case).

检查流操作 进一步解释.

更新 2:

引用 Holger 的评论:

这里的棘手之处在于对 map 和 lambda 的调用表达式在一行中,因此行断点将停在两行完全不相关的动作.

What makes it tricky here is that the call to map and the lambda expression are in one line so a line breakpoint will stop on two completely unrelated actions.

map(只允许您为 lambda 表达式设置断点.调试器不显示中间值的情况并不少见return 语句.将 lambda 更改为 n ->{ int 结果=n * 2;返回结果;}将允许您检查结果.再次插入行逐行步进时适当地中断......

Inserting a line break right after map( would allow you to set a break point for the lambda expression only. And it’s not unusual that debuggers don’t show intermediate values of a return statement. Changing the lambda to n -> { int result=n * 2; return result; } would allow you to inspect result. Again, insert line breaks appropriately when stepping line by line…

这篇关于如何使用 lambda 表达式调试 stream().map(...)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆