首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >‘'filter()’和'map()‘可以交换

‘'filter()’和'map()‘可以交换
EN

Stack Overflow用户
提问于 2021-04-07 04:48:59
回答 1查看 1.8K关注 0票数 12

我有一个简单的流程,如下所示:

代码语言:javascript
复制
List<Long> r = l.stream()
                .filter(a->a.getB() % 2 == 0)
                .map(A::getB)
                .collect(Collectors.toList());

但Intellij建议我:

可以交换

'filter()‘和'map()’检查信息:可以简化的Reports流API调用链。它允许在遍历集合时避免创建冗余的临时对象。例如:

  • collection.stream().forEach()→collection.forEach()
  • collection.stream().collect(toList/toSet/toCollection())→新CollectionType<>(collection)

Intellij给出的例子很容易理解,但我不明白为什么它建议我使用map().filter()

我查看了ReferencePipeline的来源,但没有发现任何线索:当涉及到与流实现相关的临时对象时,map().filter()filter().map()没有什么区别(如果A.b是一个原语,则filter().map()将有较少的自动装箱功能,这使我更加困惑)。

那么,我是遗漏了流实现的某个点,还是这是Intellij的错误警报?

EN

回答 1

Stack Overflow用户

发布于 2021-04-07 04:57:11

a.getB()被调用两次--一次在过滤器内,它也是映射函数,因此,与其执行两次调用,不如首先使用getB映射它,然后过滤掉它。

List<Long> r = l.stream().map(A::getB).filter(b->b % 2 == 0).collect(Collectors.toList());

编辑

如果getB返回一个long,那么可以使用mapToLong来避免中间装箱操作。

代码语言:javascript
复制
List<Long> r = l.stream()
                .mapToLong(A::getB)
                .filter(b->b % 2 == 0)
                .boxed()
                .collect(Collectors.toList());

样本输出

使用静态计数器来计数get方法的调用:

代码语言:javascript
复制
class A {
    public static int count = 0;
    private long b;

    public long getB() {
        count++;
        return b;
    }
}
代码语言:javascript
复制
List<A> list= List.of(new A(1L), new A(3L), new A(4L));
代码语言:javascript
复制
list.stream() 
    .filter(a -> a.getB()%2 == 0)
    .map(A::getB)
    .collect(Collectors.toList());
System.out.println(A.count); // returns 4

鉴于

代码语言:javascript
复制
list.stream()
    .mapToLong(A::getB)
    .filter(b->b % 2 == 0)
    .boxed()
    .collect(Collectors.toList());
System.out.println(A.count); // returns 3
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66979712

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档