[英]Java Stream equivalent of ReactiveX Observable#scan
ReactiveX has this Very Neat operator called Scan , which is like reduce, except it emits each intermediate accumulator. ReactiveX有一个名为Scan的 Very Neat运算符,它类似于reduce,只是它发出每个中间累加器。
How would I accomplish this with Java Streams? 我将如何使用Java Streams完成此任务?
Stream#reduce
is not what I want because it returns T
: Stream#reduce
不是我想要的,因为它返回T
:
T reduce(T identity, BinaryOperator<T> accumulator)
And what I want is to return Stream<T>
, with each item of the stream being the T
that was returned on each invocation of the accumulator
: 我想要的是返回
Stream<T>
,流的每个项目都是在每次调用accumulator
时返回的T
:
Stream.of(1, 2, 3)
.myScan(0, (accumulator, i) -> accumulator + i)
.collect(Collectors.toList()); // [1, 3, 6]
I could do something lame like reducing a List
, then convert back to a Stream
, but that's ugly. 我可以做一些la脚的事情,例如减少
List
,然后转换回Stream
,但这很丑陋。
Stream does not support this operation. 流不支持此操作。 You could convert it to an iterator, do it there, and convert back to streams, but there is nothing built-in for streams to do this.
您可以将其转换为迭代器,在其中进行处理,然后转换回流,但是流没有内置的功能可以执行此操作。
You could try to benefit from otherwise discouraged side-effects . 您可以尝试避免其他不利的副作用 。 Since your goal is to process the stream and keeping going on with a stream, we can achieve this using the
map
method. 由于您的目标是处理流并继续进行流处理,因此我们可以使用
map
方法来实现。 The following code does it utilizing a side-effect. 以下代码利用了副作用。
public class Scan {
public static void main(String[] args) {
Accumulator accumulator = new Accumulator();
Stream<Integer> originalStream = Stream.of(1, 2, 3);
Stream<Integer> scannedStream = originalStream
.map(i -> accumulator.accumulate(i));
List<Integer> list = scannedStream
.collect(Collectors.toList()); // [1, 3, 6]
for (Integer i : list) {
System.out.println(i);
}
}
private static class Accumulator {
private int value;
public int accumulate(int i) {
return value += i;
}
}
}
The Accumulator
can be replaced by a Function
to be used for different scan -operations. Accumulator
可以由Function
替换,以用于不同的扫描操作。
But you have to be aware of the restrictions and concerns (eg thread-safty). 但是您必须意识到限制和担忧(例如线程安全性)。
The biggest problem of java-stream is that is overrated and understood as a magic-bullet solution for everything slightly related to any of Collection. java-stream的最大问题是,它被高估了,并且被认为是与Collection稍有相关的所有事物的魔术子弹解决方案。
This API has been build for the supporting sequential processing of the elements. 构建此API是为了支持元素的顺序处理。 There doesn't exist any Stream-alike method performing the snippet below.
尚无任何类似Stream的方法执行以下代码段。 Moreover, this API is not easily extendable.
而且,此API难以扩展。
Here is what you are speaking about: 这是您正在谈论的内容:
List<Integer> list = new ArrayList<>();
Stream.of(1, 2, 3).reduce(0, (t, u) -> {
final Integer s = t + u;
list.add(s);
return s;
});
System.out.println(list); // prints [1, 3, 6]
And here is a workaround using AtomicInteger
which allows you to continue the streaming after performing the map(..)
: 这是使用
AtomicInteger
一种解决方法,它允许您在执行map(..)
之后继续进行流式处理:
AtomicInteger sum = new AtomicInteger(0);
List<Integer> list = Stream.of(1, 2, 3)
.map(i -> sum.addAndGet(i))
.collect(Collectors.toList());
System.out.println(list); // prints [1, 3, 6]
Sometimes you have to use different way. 有时您必须使用其他方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.