Java Streams concat Streams with Supplier 其次是不同的(惰性评估行为)
Java Streams concat Streams with Supplier followed by distinct (lazy evaluation behavior)
我有一个像这样的简单代码
import java.util.function.Supplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class StreamSupplierVersusConcat {
public static void main(String[] args) {
final StreamSupplierVersusConcat clazz = new StreamSupplierVersusConcat();
clazz.doConcat();
}
private void doConcat(){
System.out.println(Stream.concat(buildStreamFromRange(0,1000).get()
,buildStreamFromRange(1000,2000).get())
.anyMatch("1"::equals));
}
private Supplier<Stream<String>>buildStreamFromRange(final int start,final int end){
return ()->IntStream.range(start, end)
.mapToObj(i->{
System.out.println("index At: "+i);
return String.valueOf(i);
});
}
}
我知道 concat 是惰性的,所以当我 运行 我看到的代码只生成 2 个值,这很好,但知道 distinct 是一个有状态的操作,我认为将该方法放在 Stream 管道上Stream 会生成所有值然后执行 anyMatch 方法但是如果我这样说
private void doConcat(){
System.out.println(Stream.concat(buildStreamFromRange(0,1000).get()
,buildStreamFromRange(1000,2000).get())
.distinct()//ARE ALL THE VALUES GENERATED NOT REQUIRED HERE???
.anyMatch("1"::equals));
}
但是无论有无 distinct,我都会得到相同的响应。
index At: 0
index At: 1
true
我错过了什么? 我认为 distinct 会在 anyMatch 看到之前看到所有项目。
在 Java 8.
上测试
非常感谢。
在简历中我的理解是 我认为 distinct 会在 anyMatch 看到任何之前看到所有项目。 不正确这个例子解释了它。
private void distinctIsNotABlockingCall(){
final boolean match = Stream.of("0","1","2","3","4","5","6","7","8","8","8","9","9","9","9","9","9","9","9","9","10","10","10","10")
.peek(a->System.out.println("before: "+a))
.distinct()//I THOUGHT THAT NOT ANYMATCH WAS CALLED AFTER DISTINCT HANDLE ALL THE ITEMS BUT WAS WRONG.
.peek(a->System.out.println("after: "+a))
.anyMatch("10"::equals);
System.out.println("match? = " + match);
}
before: 0
after: 0
before: 1
after: 1
before: 2
after: 2
before: 3
after: 3
before: 4
after: 4
before: 5
after: 5
before: 6
after: 6
before: 7
after: 7
before: 8
after: 8
before: 8 distinct working
before: 8 distinct working
before: 9
after: 9
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 10
after: 10
match? = true
您可以看到 distinct 收到了重复值和非重复值,而且 anyMatch 收到了那些非重复值,并且 distinct 和 anyMatch 正在同时工作,非常感谢。
Streams are lazy because intermediate operations are not evaluated
unless terminal operation is invoked. check SO answer here
据我所知,Stream Api 流式传输每个元素,直到应用终端操作,然后流式传输下一个元素。
这也说明了这里的情况。元素 "0"
被流式传输,不满足终端操作。还有一个需要推流,"1"
现在,终端操作 .anyMatch("1"::equals));
满足。无需流式传输更多元素。 Distinct 将在两者之间被调用,而无需更改流元素。
因此,如果您在 "0"
之后还有另一个 "0"
要进行流式传输,则它根本不会到达终端操作。
private void doConcat(){
System.out.println(Stream.concat(buildStreamFromRange(0,1000).get()
,buildStreamFromRange(1000,2000).get())
.distinct()
.peek( e -> System.out.println(e))
.anyMatch("1"::equals));
尝试添加 peek 并尝试在开头流式传输 2 "0"
个元素。其中只有 1 个会通过流程并从 peek 打印出来。
Peek 也可用于调试目的,并在您不确定时查看流程的行为,因此在将来使用它对您有利。
供未来读者参考的简单示例:
下面是一个更简单的例子,未来的读者将能够理解流中的惰性运算符是如何工作的:
Stream.of("0","0","1","2","3","4")
.distinct()
.peek(a->System.out.println("after distinct: "+a))
.anyMatch("1"::equals);
将打印
after distinct: 0
after distinct: 1
首先"0"
一直走到终端操作却不满足。必须流式传输另一个元素。
第二个"0"
通过.distinct()
过滤,永远不会到达终端操作
终端操作还没满足,流下一个元素
"1"
经过终端操作,满足
不需要流式处理更多元素。
我有一个像这样的简单代码
import java.util.function.Supplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class StreamSupplierVersusConcat {
public static void main(String[] args) {
final StreamSupplierVersusConcat clazz = new StreamSupplierVersusConcat();
clazz.doConcat();
}
private void doConcat(){
System.out.println(Stream.concat(buildStreamFromRange(0,1000).get()
,buildStreamFromRange(1000,2000).get())
.anyMatch("1"::equals));
}
private Supplier<Stream<String>>buildStreamFromRange(final int start,final int end){
return ()->IntStream.range(start, end)
.mapToObj(i->{
System.out.println("index At: "+i);
return String.valueOf(i);
});
}
}
我知道 concat 是惰性的,所以当我 运行 我看到的代码只生成 2 个值,这很好,但知道 distinct 是一个有状态的操作,我认为将该方法放在 Stream 管道上Stream 会生成所有值然后执行 anyMatch 方法但是如果我这样说
private void doConcat(){
System.out.println(Stream.concat(buildStreamFromRange(0,1000).get()
,buildStreamFromRange(1000,2000).get())
.distinct()//ARE ALL THE VALUES GENERATED NOT REQUIRED HERE???
.anyMatch("1"::equals));
}
但是无论有无 distinct,我都会得到相同的响应。
index At: 0
index At: 1
true
我错过了什么? 我认为 distinct 会在 anyMatch 看到之前看到所有项目。 在 Java 8.
上测试非常感谢。
在简历中我的理解是 我认为 distinct 会在 anyMatch 看到任何之前看到所有项目。 不正确这个例子解释了它。
private void distinctIsNotABlockingCall(){
final boolean match = Stream.of("0","1","2","3","4","5","6","7","8","8","8","9","9","9","9","9","9","9","9","9","10","10","10","10")
.peek(a->System.out.println("before: "+a))
.distinct()//I THOUGHT THAT NOT ANYMATCH WAS CALLED AFTER DISTINCT HANDLE ALL THE ITEMS BUT WAS WRONG.
.peek(a->System.out.println("after: "+a))
.anyMatch("10"::equals);
System.out.println("match? = " + match);
}
before: 0
after: 0
before: 1
after: 1
before: 2
after: 2
before: 3
after: 3
before: 4
after: 4
before: 5
after: 5
before: 6
after: 6
before: 7
after: 7
before: 8
after: 8
before: 8 distinct working
before: 8 distinct working
before: 9
after: 9
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 9 distinct working
before: 10
after: 10
match? = true
您可以看到 distinct 收到了重复值和非重复值,而且 anyMatch 收到了那些非重复值,并且 distinct 和 anyMatch 正在同时工作,非常感谢。
Streams are lazy because intermediate operations are not evaluated unless terminal operation is invoked. check SO answer here
据我所知,Stream Api 流式传输每个元素,直到应用终端操作,然后流式传输下一个元素。
这也说明了这里的情况。元素 "0"
被流式传输,不满足终端操作。还有一个需要推流,"1"
现在,终端操作 .anyMatch("1"::equals));
满足。无需流式传输更多元素。 Distinct 将在两者之间被调用,而无需更改流元素。
因此,如果您在 "0"
之后还有另一个 "0"
要进行流式传输,则它根本不会到达终端操作。
private void doConcat(){
System.out.println(Stream.concat(buildStreamFromRange(0,1000).get()
,buildStreamFromRange(1000,2000).get())
.distinct()
.peek( e -> System.out.println(e))
.anyMatch("1"::equals));
尝试添加 peek 并尝试在开头流式传输 2 "0"
个元素。其中只有 1 个会通过流程并从 peek 打印出来。
Peek 也可用于调试目的,并在您不确定时查看流程的行为,因此在将来使用它对您有利。
供未来读者参考的简单示例:
下面是一个更简单的例子,未来的读者将能够理解流中的惰性运算符是如何工作的:
Stream.of("0","0","1","2","3","4")
.distinct()
.peek(a->System.out.println("after distinct: "+a))
.anyMatch("1"::equals);
将打印
after distinct: 0
after distinct: 1
首先"0"
一直走到终端操作却不满足。必须流式传输另一个元素。
第二个"0"
通过.distinct()
过滤,永远不会到达终端操作
终端操作还没满足,流下一个元素
"1"
经过终端操作,满足
不需要流式处理更多元素。