【问题标题】:Use same variable in filter() and map() of a Java 8 stream在 Java 8 流的 filter() 和 map() 中使用相同的变量
【发布时间】:2020-03-29 04:02:52
【问题描述】:

为了提高性能,我想在 Java 8 流的 filter()map() 中使用相同的变量。 例子-

                list.stream()
                .filter(var -> getAnotherObject(var).isPresent())
                .map(var -> getAnotherObject(var).get())
                .collect(Collectors.toList())

被调用的方法getAnotherObject()看起来像-

private Optional<String> getAnotherObject(String var)

在上述场景中,我必须调用方法 getAnotherObject() 两次。
如果我使用常规 for 循环,那么我必须调用方法 getAnotherObject() 一次。

List<String> resultList = new ArrayList<>();
        for(String var : list) {
            Optional<String> optionalAnotherObject = getAnotherObject(var);
            if(optionalAnotherObject.isPresent()) {
                String anotherObject = optionalAnotherObject.get();
                resultList.add(anotherObject)
            }
        }

即使使用流,我也可以将所有代码放入 map()-

list.stream()
                .map(var -> {
                    Optional<String> anotherObjectOptional = getAnotherObject(var);
                    if(anotherObjectOptional.isPresent()) {
                        return anotherObjectOptional.get();
                    }
                    return null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

但我相信一定有一种优雅的方式使用filter()

【问题讨论】:

  • list.stream().map(var -&gt; getAnotherObject(var)).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());(未经测试,我只是不明白为什么这在我脑海中不起作用)。
  • 您是否从该解决方案中获得了很多性能提升?
  • 你最后的方法还不错。只需将if(anotherObjectOptional.isPresent()) { return anotherObjectOptional.get(); } return null; 替换为.orElse(null)。换句话说,将整个步骤简化为.map(var -&gt; getAnotherObject(var).orElse(null) .filter(Objects::nonNull)。在 Java 9 中,您可以简单地使用 .flatMap(var -&gt; getAnotherObject(var).stream())
  • @Kayaman:如果 getAnotherObject() 方法正在执行一些重量级的过程,那么它肯定值得避免第二次调用 + 为同一目的两次调用相同的方法是一种不好的做法!
  • @Holger :这确实是一个避免map() 链的优雅解决方案......我会试一试......

标签: java filter collections java-8 java-stream


【解决方案1】:

你可以像这样创建一个流

list.stream()
        .map(YourClass::getAnotherObject)
        .filter(Optional::isPresent)
        .map(Optional::get)
        .collect(Collectors.toList());

YourClass指的是定义getAnotherObject方法的类的名称

【讨论】:

  • 这将导致List&lt;Optional&lt;T&gt;&gt;。他们提供的代码导致List&lt;T&gt;。 (并不是说这不是一个简单的解决方案......只是行为上的不同。)编辑已经解决了这个 +1。
【解决方案2】:

您可以使用flatMap。通常这用于展平东西,但在这里你可以

  1. 如果可选元素有值,则将元素映射到该元素
  2. 如果可选项没有值,则将元素映射到空流

像这样:

stream
    .map(x -> getAnotherObject(x))
    .flatMap(x -> x.map(Stream::of).orElse(Stream.of())))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    • 2022-06-18
    • 1970-01-01
    • 2023-03-04
    相关资源
    最近更新 更多