从流中收集连续的对

新手上路,请多包涵

给定一个流,例如 { 0, 1, 2, 3, 4 }

我怎样才能最优雅地将它转换成给定的形式:

{ new Pair(0, 1), new Pair(1, 2), new Pair(2, 3), new Pair(3, 4) }

(当然,假设我已经定义了类 Pair)?

编辑: 这不是严格意义上的整数或原始流。对于任何类型的流,答案应该是通用的。

原文由 Aleksandr Dubinsky 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 474
2 个回答

我的扩展标准流的 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);

此功能是使用 自定义 spliterator 实现的。它的开销很低,可以很好地并行化。当然,它适用于任何流源,而不仅仅是像许多其他解决方案那样的随机访问列表/数组。在许多测试中,它的表现非常出色。 这是 一个 JMH 基准测试,我们在其中使用不同的方法找到较大值之前的所有输入值(请参阅 问题)。

原文由 Tagir Valeev 发布,翻译遵循 CC BY-SA 3.0 许可协议

Java 8 流库主要用于将流拆分为更小的块以进行并行处理,因此有状态管道阶段非常有限,并且不支持执行诸如获取当前流元素的索引和访问相邻流元素之类的操作。

解决这些问题的典型方法(当然有一些限制)是通过索引驱动流,并依赖于在某些随机访问数据结构(例如可以从中检索元素的 ArrayList)中处理值。如果值在 arrayList 中,则可以通过执行以下操作按要求生成对:

     IntStream.range(1, arrayList.size())
             .mapToObj(i -> new Pair(arrayList.get(i-1), arrayList.get(i)))
             .forEach(System.out::println);

当然,限制是输入不能是无限流。不过,该管道可以并行运行。

原文由 Stuart Marks 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题