为了账号安全,请及时绑定邮箱和手机立即绑定

从流中收集连续对

从流中收集连续对

ABOUTYOU 2019-07-20 10:29:19
从流中收集连续对给定一个流,如{ 0, 1, 2, 3, 4 },我如何才能最优雅地将它转化为给定的形式:{ new Pair(0, 1), new Pair(1, 2), new Pair(2, 3), new Pair(3, 4) }(当然,假设我已经定义了类对)?编辑:严格地说,这并不是关于INT或原始流的。对于任何类型的流,答案都应该是通用的。
查看完整描述

3 回答

?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

我的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基准测试,在该基准测试中,我们使用不同的方法在较大值之前找到所有输入值(请参见这,这个问题)。


查看完整回答
反对 回复 2019-07-20
?
至尊宝的传说

TA贡献1789条经验 获得超10个赞

Java 8流库主要用于将流分割成较小的块进行并行处理,因此有状态管道阶段非常有限,并且不支持获取当前流元素的索引和访问相邻的流元素。

当然,解决这些问题的一个典型方法是按索引驱动流,并依赖于在一些随机访问数据结构中处理的值,比如ArrayList,从中可以检索元素。如果值在arrayList,可以根据请求生成对,方法如下:

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

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


查看完整回答
反对 回复 2019-07-20
?
温温酱

TA贡献1752条经验 获得超4个赞

这不是一种优雅的解决方案,它是一种简单的解决方案,但适用于无限流

Stream<Pair> pairStream = Stream.iterate(0, (i) -> i + 1).map( // natural numbers
    new Function<Integer, Pair>() {
        Integer previous;

        @Override
        public Pair apply(Integer integer) {
            Pair pair = null;
            if (previous != null) pair = new Pair(previous, integer);
            previous = integer;
            return pair;
        }
    }).skip(1); // drop first null

现在,您可以将您的流限制在您想要的长度。

pairStream.limit(1_000_000).forEach(i -> System.out.println(i));

P.S.我希望有更好的解决方案,比如Clojure(partition 2 1 stream)


查看完整回答
反对 回复 2019-07-20
  • 3 回答
  • 0 关注
  • 320 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信