Java ';过滤器()';和';map()';可以交换
我有一个简单的流,如下所示:Java ';过滤器()';和';map()';可以交换,java,intellij-idea,java-stream,Java,Intellij Idea,Java Stream,我有一个简单的流,如下所示: List r=l.stream() .filter(a->a.getB()%2==0) .map(A::getB) .collect(Collectors.toList()); 但Intellij建议我: “filter()”和“map()”可以互换 检验信息:报告流API调用链,可以简化。它允许在遍历集合时避免创建冗余的临时对象。e、 g collection.stream().forEach()→ collection.forEach() collectio
List r=l.stream()
.filter(a->a.getB()%2==0)
.map(A::getB)
.collect(Collectors.toList());
但Intellij建议我:
“filter()”和“map()”可以互换
检验信息:报告流API调用链,可以简化。它允许在遍历集合时避免创建冗余的临时对象。e、 g
- collection.stream().forEach()→ collection.forEach()
- collection.stream().collect(toList/toSet/toCollection())→ 新集合类型(集合)
map().filter()
我查看了ReferencePipeline
的源代码,但没有找到任何线索:map().filter()
或filter().map()
对于与流实现相关的临时对象没有什么区别(filter().map()
如果A.b
是一个原语,那么它的自动装箱功能就会减少,这让我更加困惑)
那么,我是否缺少一些流点实现,或者这是Intellij的错误警报?a.getB()
被调用两次-一次在过滤器内部,它也是映射函数,因此与其这样做两次,不如先使用getB
映射它,然后过滤掉它
List r=l.stream().map(A::getB).filter(b->b%2==0).collect(Collectors.toList())代码>
编辑
如果getB
返回long
,则可以使用mapToLong
来避免中间装箱操作
List r=l.stream()
.mapToLong(A::getB)
.filter(b->b%2==0)
.boxed()
.collect(Collectors.toList());
样本输出
使用静态计数器对get方法的调用进行计数:
A类{
公共静态整数计数=0;
私人长b;
公共长getB(){
计数++;
返回b;
}
}
List List=List.of(新A(1L)、新A(3L)、新A(4L));
list.stream()
.filter(a->a.getB()%2==0)
.map(A::getB)
.collect(Collectors.toList());
System.out.println(A.count);//返回4
鉴于
list.stream()
.mapToLong(A::getB)
.filter(b->b%2==0)
.boxed()
.collect(Collectors.toList());
System.out.println(A.count);//返回3
但这里的具体优化是什么?假设列表中有数十亿个元素,其中%10个元素是偶数。。。在映射所有更优化的元素之前不会进行过滤。(我的意思是CPU周期)@AliCan关键是你需要调用同一个getter来进行筛选,这并不能避免文章中提到的冗余。@AliCan筛选函数也在调用getB
。假设有100个元素,10个元素是偶数。由于getB
在filter
和map
中都存在,因此它将被调用100+10次。但是如果你映射然后过滤,getB
只会被调用100次。@ArvindKumarAvinash我试着用一个静态计数器运行,对于一个包含3个元素的列表,1个偶数,所讨论的代码的计数器值的输出是4
而不是6
。谢谢大家,我的错了。事实上,现在很明显。