java - 在过滤器 findAny 之前, map 是否应用于所有列表?

标签 java java-8 java-stream short-circuiting

我想过滤列表以查找具有非空属性的元素并返回该属性:

list.stream.map(a -> StringUtils.trimToEmpty(a.getProp())).filter( p -> StringUtils.isNotEmpty(p)).findAny().orElse("");

上面的代码是否首先映射了所有元素?出于效率原因,我想逐个元素进行处理。

最佳答案

Stream::findAnyshort-circuiting terminal operation ,简而言之,这意味着如果存在某个项目,它将终止 Stream。

即。如果第一个元素符合 Stream::filter 管道的条件并将其传递出去,则 Stream::findAny 会立即返回它,而不会处理原始集合中的其他元素。

有一个很好的证据,使用 Stream::peek 来理解 Stream API 的工作原理(假设类 Foo 只有一个最终字符串参数 prop):

List<Foo> list = List.of(
   new Foo(""),            // the first is empty and doesn't pass through Stream::filter
   new Foo("one"),         // this is qualified
   new Foo("two"));        // this is qualified

list.stream()
    .peek(item -> System.out.println("# Streamed    " + item.getProp())) // streamed
    .map(a -> StringUtils.trimToEmpty(a.getProp()))
    .peek(item -> System.out.println("#  Mapped     " + item))           // mapped
    .filter(StringUtils::isNotEmpty)
    .peek(item -> System.out.println("#   Filtered  " + item))           // filtered
    .findAny()
    .orElse("");

输出显示第一个元素未通过 Stream::filter(为空)并在 Stream::map 之前结束。第二个元素通过 Stream::filter 和后续的 Stream::map 并最终到达 Stream::findAny。只要 Stream::findAny 是一个具有当前结果的短路和终止操作,它就会终止 Stream。

# Streamed    
#  Mapped     
# Streamed    one
#  Mapped     one
#   Filtered  one

关于java - 在过滤器 findAny 之前, map 是否应用于所有列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63074620/

相关文章:

java - 使用stream和lambda美化for循环

java - 如何将多部分文件转换为文件?

java - 为什么我的数据没有持久化?

java - 如何将 Java lambda 表达式用于正则表达式

java - 如何使用 Java 8 Optionals,如果所有三个都存在则执行一个 Action ?

Java 8 流查看和限制交互

java - 用于替换嵌套 for 循环的 Lambda 表达式由于某种原因不起作用

java - 将用户输入添加到 Java 程序

java - Spring Data Neo4j 未将类字段映射到节点属性

<JDK8 兼容性中的 Java 三元运算符与 if/else