如何在java8(可能是memoization进程)中重用已经通过流迭代计算的值?
如果流重复或再次提供,则将重新计算。在某些情况下,最好为该CPU时间交换内存。从头开始收集所有内容可能不是一个好主意,因为流用于查找满足谓词的第一个项。
Stream<Integer> all = Stream.of(1,2,3,4,5, ...<many other values>... ).
map(x->veryLongTimeToComputeFunction(x));
System.out.println("fast find of 2"+all.filter(x->x>1).findFirst());
//both of these two lines generate a "java.lang.IllegalStateException: stream has already been operated upon or closed"
System.out.println("no find"+all.filter(x->x>10).findFirst());
System.out.println("find again"+all.filter(x->x>4).findFirst());
问题是Copy a stream to avoid "stream has already been operated upon or closed" (java 8)
答案 0 :(得分:1)
为什么不在veryLongTimeToComputeFunction
内使用记忆?您可以将memo cache作为参数添加到func。
答案 1 :(得分:1)
规范的内存中的Stream源是一个Collection。一个简单的,不能并行的Stream Memoization可以实现如下:
public static void main(String[] args) {
Supplier<Stream<Integer>> s=memoize(
IntStream.range(0, 10_000)
.map(x -> veryLongTimeToComputeFunction(x))
);
System.out.println("First item > 1 "+s.get().filter(x -> x>1 ).findFirst());
System.out.println("First item > 10 "+s.get().filter(x -> x>10).findFirst());
System.out.println("First item > 4 "+s.get().filter(x -> x>4 ).findFirst());
}
static int veryLongTimeToComputeFunction(int arg) {
System.out.println("veryLongTimeToComputeFunction("+arg+")");
return arg;
}
public static <T> Supplier<Stream<T>> memoize(BaseStream<T,?> stream) {
Spliterator<T> sp=stream.spliterator();
class S extends Spliterators.AbstractSpliterator<T> {
ArrayList<T> mem=new ArrayList<>();
S() { super(sp.estimateSize(), sp.characteristics()); }
public boolean tryAdvance(Consumer<? super T> action) {
return sp.tryAdvance(item -> {
mem.add(item);
action.accept(item);
});
}
}
S s=new S();
return () -> Stream.concat(s.mem.stream(), StreamSupport.stream(s, false));
}
在向供应商请求下一个Stream之前,请务必完成Stream处理。
答案 2 :(得分:0)
我建议您将Stream
收集到列表中,然后在列表的流中运行过滤器。
答案 3 :(得分:0)
流不是已保存,它们即将处理数据。
示例:你正在观看一个DVD,用java术语说dvd就像一个集合,从你的dvd播放器转移到你的电视的数据就是一个流。你无法保存流,但你可以刻录光盘,用java术语收集它。
还有其他选择:
答案 4 :(得分:0)
Java 8流本质上是懒惰的。对流执行的操作按垂直顺序进行评估。 您可以使用以下代码实现您想要实现的目标:
Stream.of(1,2,3,4,5, ...<many other values>... )
.map(x-> veryLongTimeToComputeFunction(x))
.filter(x-> x > 1)
.findFirst();
这将确保仅调用veryLongTimeToComputeFunction(),直到找不到匹配的第一个元素。之后,操作将终止。 在最坏的情况下,如果最后一个数字是符合条件的数字,那么将为所有数字调用veryLongTimeToComputeFunction。
此外,您可以将并行流与findAny()方法结合使用。它会加快表现。