Java 小溪神秘地消耗了两次
以下代码以Java 小溪神秘地消耗了两次,java,java-stream,Java,Java Stream,以下代码以java.lang.IllegalStateException结束:流已被操作或关闭 public static void main(String[] args) { Stream.concat(Stream.of("FOOBAR"), reverse(StreamSupport.stream(new File("FOO/BAR").toPath().spliterator(), true)
java.lang.IllegalStateException结束:流已被操作或关闭
public static void main(String[] args) {
Stream.concat(Stream.of("FOOBAR"),
reverse(StreamSupport.stream(new File("FOO/BAR").toPath().spliterator(), true)
.map(Path::toString)));
}
static <T> Stream<T> reverse(Stream<T> stream) {
return stream.reduce(Stream.empty(),
(Stream<T> a, T b) -> Stream.concat(Stream.of(b), a),
(a, b) -> Stream.concat(b, a));
}
publicstaticvoidmain(字符串[]args){
康卡特河(福巴河),
反向(StreamSupport.stream(新文件(“FOO/BAR”).toPath().spliterator(),true)
.map(路径::toString));
}
静态流反转(流){
返回stream.reduce(stream.empty(),
(a流,T流)->浓缩液(b流,a流),
(a,b)->Stream.concat(b,a));
}
显而易见的解决方案是使用StreamSupport.stream(…,false)
生成一个非并行流,但我不明白为什么不能并行运行。stream.empty()
不是一个常量。此方法在每次调用时返回一个新的流实例,该实例将像任何其他流一样被使用,例如,当您将其传递到stream.concat
中时
因此,Stream.empty()。这是一个实现细节,碰巧只用于一次顺序缩减,而可能用于多次并行缩减
你可以用
静态流反向(流){
返回stream.map(stream::of)
.reduce((a,b)->Stream.concat(b,a))
.orElseGet(流::空);
}
相反
然而,我只提供了一个学术练习的解决方案。一旦流变大,就会导致过多的concat
调用,注意:
从重复连接构造流时请小心。访问深度连接流的元素可能导致深度调用链,甚至stackoverflowerr
通常,当以这种方式使用流API时,生成的底层数据结构将比平面列表昂贵得多
你可以用像
streams=Stream.concat(Stream.of(“FOOBAR”),
反向(新文件(“FOO/BAR”).toPath()).map(路径::toString));
静态流反向(路径p){
ArrayDeque d=新的ArrayDeque();
p、 forEach(d::addFirst);
返回d.stream();
}
或
静态流反向(路径p){
Stream.Builder b=Stream.Builder();
对于(;p!=null;p=p.getParent())b.add(p.getFileName());
返回b.build();
}
使用Java 9+时,您可以使用真正没有额外存储的流(这并不一定意味着它会更高效):
静态流反向(路径p){
返回Stream.iterate(p,Objects::nonNull,Path::getParent).map(Path::getFileName);
}
Stream.empty()
不是常数。此方法在每次调用时返回一个新的流实例,该实例将像任何其他流一样被使用,例如,当您将其传递到stream.concat
中时
因此,Stream.empty()。这是一个实现细节,碰巧只用于一次顺序缩减,而可能用于多次并行缩减
你可以用
静态流反向(流){
返回stream.map(stream::of)
.reduce((a,b)->Stream.concat(b,a))
.orElseGet(流::空);
}
相反
然而,我只提供了一个学术练习的解决方案。一旦流变大,就会导致过多的concat
调用,注意:
从重复连接构造流时请小心。访问深度连接流的元素可能导致深度调用链,甚至stackoverflowerr
通常,当以这种方式使用流API时,生成的底层数据结构将比平面列表昂贵得多
你可以用像
streams=Stream.concat(Stream.of(“FOOBAR”),
反向(新文件(“FOO/BAR”).toPath()).map(路径::toString));
静态流反向(路径p){
ArrayDeque d=新的ArrayDeque();
p、 forEach(d::addFirst);
返回d.stream();
}
或
静态流反向(路径p){
Stream.Builder b=Stream.Builder();
对于(;p!=null;p=p.getParent())b.add(p.getFileName());
返回b.build();
}
使用Java 9+时,您可以使用真正没有额外存储的流(这并不一定意味着它会更高效):
静态流反向(路径p){
返回Stream.iterate(p,Objects::nonNull,Path::getParent).map(Path::getFileName);
}
reduce(…)
fromreverse(Stream)
是一个终端操作。当然,reduce将消耗整个拆分器,但它从中生成的流应该是可用的。为什么在生成非并行流时不使用它?reduce(…)
fromreverse(stream)
是一个终端操作。当然,reduce会消耗整个拆分器,但它从中生成的流应该是可用的。为什么在生成非并行流时不消耗它?