如何使用 lambda 表达式调试 stream().map(...)? [英] How to debug stream().map(...) with lambda expressions?
问题描述
在我们的项目中,我们正在迁移到 Java 8 并测试它的新功能.
In our project we are migrating to java 8 and we are testing the new features of it.
在我的项目中,我使用 Guava 谓词和函数来过滤和转换一些使用 Collections2.transform
和 Collections2.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屋!