从流中收集连续的对
2022-08-31 09:17:11
给定一个流,例如 ,{ 0, 1, 2, 3, 4 }
我怎样才能最优雅地把它变成给定的形式:
{ new Pair(0, 1), new Pair(1, 2), new Pair(2, 3), new Pair(3, 4) }
(当然,假设我已经定义了类对)?
编辑:这并不是严格意义上的 int 或原始流。对于任何类型的流,答案都应该是一般的。
给定一个流,例如 ,{ 0, 1, 2, 3, 4 }
我怎样才能最优雅地把它变成给定的形式:
{ new Pair(0, 1), new Pair(1, 2), new Pair(2, 3), new Pair(3, 4) }
(当然,假设我已经定义了类对)?
编辑:这并不是严格意义上的 int 或原始流。对于任何类型的流,答案都应该是一般的。
Java 8 流库主要面向将流拆分为较小的块以进行并行处理,因此有状态管道阶段非常有限,并且不支持执行诸如获取当前流元素的索引和访问相邻的流元素之类的操作。
当然,解决这些问题(有一些限制)的典型方法是通过索引驱动流,并依赖于在一些随机访问数据结构(如ArrayList)中处理值,从中可以检索元素。如果值在 中,则可以通过执行如下操作来生成请求的对:arrayList
IntStream.range(1, arrayList.size())
.mapToObj(i -> new Pair(arrayList.get(i-1), arrayList.get(i)))
.forEach(System.out::println);
当然,限制是输入不能是无限流。不过,此管道可以并行运行。
扩展标准流的我的 StreamEx 库为所有流类型提供了 pairMap
方法。对于原始流,它不会更改流类型,但可用于进行一些计算。最常见的用法是计算差异:
int[] pairwiseDiffs = IntStreamEx.of(input).pairMap((a, b) -> (b-a)).toArray();
对于对象流,您可以创建任何其他对象类型。我的库不提供任何新的用户可见数据结构,例如(这是库概念的一部分)。但是,如果您有自己的类并希望使用它,则可以执行以下操作:Pair
Pair
Stream<Pair> pairs = IntStreamEx.of(input).boxed().pairMap(Pair::new);
或者,如果您已经拥有一些:Stream
Stream<Pair> pairs = StreamEx.of(stream).pairMap(Pair::new);
此功能是使用自定义拆分器实现的。它具有非常低的开销,并且可以很好地并行化。当然,它适用于任何流源,而不仅仅是像许多其他解决方案那样的随机访问列表/数组。在许多测试中,它的表现非常好。这是一个 JMH 基准测试,我们使用不同的方法查找较大值之前的所有输入值(请参阅此问题)。