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

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

问题描述

在我们的项目中,我们正在迁移到java 8,我们正在测试它的新功能。



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



在这种迁移中,我需要将guava代码更改为java 8更改。所以,我所做的更改是:

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

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

收集结果= Collections2.transform(自然,重复);

To ...

 列表<整数> result2 = naturals.stream()
.map(n - > n * 2)
.collect(Collectors.toList());

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



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

  @Hidden 
@DontInline
/ **在给定的内容上解释性地调用此表单争论* /
对象解释WithArguments(Object ... argumentValues)throws Throwable {
if(TRACE_INTERPRETER)
return interpretWithArgumentsTracing(argumentValues);
checkInvocationCounter();
assert(arityCheck(argumentValues));
Object [] values = Arrays.copyOf(argumentValues,names.length); (int i = argumentValues.length; i< values.length; i ++){
values [i] = interpretName(names [i],values);

}
return(result< 0)? null:values [result];
}

但是它并不像Guava调试代码那样直观,实际上我找不到 n * 2 转换。



有没有办法看到这种转换或一种方式简单调试此代码?



编辑:我已经添加了不同评论和发布的答案



感谢 Holger 评论回答了我的问题,使用lambda块的方法让我看到转换过程并调试了lambda体内发生了什么: p>

  .map(
n - > {
整数nr = n * 2;
返回nr ;
}

感谢 Stuart Marks 使用方法引用的方法也允许我调试转换过程:

  static int timesTwo int n){
整数结果= n * 2;
返回结果;
}
...
列表<整数> result2 = naturals.stream()
.map(Java8Test :: timesTwo)
.collect(Collectors.toList());
...

感谢 Marlon Bernardes 答案我注意到我的Eclipse没有显示它应该和peek()的用法有助于显示结果。

解决方案

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



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

 列表<整数> 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体没有被执行。您需要设置一个断点,并在终端操作被调用后检查(收集,在这种情况下)。



检查流操作以进一步解释。



更新2:



引用霍尔的评论:


这里有什么困难的是,地图和lambda
表达式在一行中,所以线断点将停止在两个
完全不相关的操作上。



map(
)之后插入换行符将允许您设置断点lambda表达式
调试器不显示
a return 语句的中间值并不常见,将lambda更改为 n - > {int result = n * 2; return result;}
将允许您检查结果再一次插入行
...



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 some collections using Collections2.transform and Collections2.filter.

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

To...

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

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];
}

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?

EDIT: I've added answer from different comments and posted answers

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

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

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.

解决方案

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

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

UPDATE:

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).

Check Stream Operations for further explanations.

UPDATE 2:

Quoting Holger's comment:

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.

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天全站免登陆