我想过滤列表以查找具有非空属性的元素并返回该属性:
list.stream.map(a -> StringUtils.trimToEmpty(a.getProp())).filter( p -> StringUtils.isNotEmpty(p)).findAny().orElse("");
上面的代码是否首先映射了所有元素?出于效率原因,我想逐个元素进行处理。
最佳答案
Stream::findAny
是 short-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/