当前位置:  开发笔记 > 编程语言 > 正文

如何将Java流转换为滑动窗口?

如何解决《如何将Java流转换为滑动窗口?》经验,为你挑选了3个好方法。

将流转换为滑动窗口的推荐方法是什么?

例如,在Ruby中你可以使用each_cons:

irb(main):020:0> [1,2,3,4].each_cons(2) { |x| puts x.inspect }
[1, 2]
[2, 3]
[3, 4]
=> nil
irb(main):021:0> [1,2,3,4].each_cons(3) { |x| puts x.inspect }
[1, 2, 3]
[2, 3, 4]
=> nil

在Guava中,我发现只有Iterators#partition,它是相关的但没有滑动窗口:

final Iterator> partition =
   Iterators.partition(IntStream.range(1, 5).iterator(), 3);
partition.forEachRemaining(System.out::println);
-->
[1, 2, 3]
[4]

Tagir Valeev.. 17

API中没有这样的功能,因为它支持顺序和并行处理,并且很难为任意流源提供滑动窗口函数的有效并行处理(即使是高效的并行处理对很难,我实现了它,所以我知道).

但是,如果您的源是List快速随机访问,您可以使用subList()方法来获得所需的行为,如下所示:

public static  Stream> sliding(List list, int size) {
    if(size > list.size()) 
        return Stream.empty();
    return IntStream.range(0, list.size()-size+1)
                    .mapToObj(start -> list.subList(start, start+size));
}

类似的方法实际上可以在我的StreamEx库中找到:参见StreamEx.ofSubLists().

还有一些其他第三方解决方案不关心并行处理,并使用一些内部缓冲区提供滑动功能.例如,质子包StreamUtils.windowed.



1> Tagir Valeev..:

API中没有这样的功能,因为它支持顺序和并行处理,并且很难为任意流源提供滑动窗口函数的有效并行处理(即使是高效的并行处理对很难,我实现了它,所以我知道).

但是,如果您的源是List快速随机访问,您可以使用subList()方法来获得所需的行为,如下所示:

public static  Stream> sliding(List list, int size) {
    if(size > list.size()) 
        return Stream.empty();
    return IntStream.range(0, list.size()-size+1)
                    .mapToObj(start -> list.subList(start, start+size));
}

类似的方法实际上可以在我的StreamEx库中找到:参见StreamEx.ofSubLists().

还有一些其他第三方解决方案不关心并行处理,并使用一些内部缓冲区提供滑动功能.例如,质子包StreamUtils.windowed.



2> Lukas Eder..:

如果您愿意使用第三方库而不需要并行性,那么jOOλ提供SQL风格的窗口函数如下

int n = 2;

System.out.println(
Seq.of(1, 2, 3, 4)
   .window(0, n - 1)
   .filter(w -> w.count() == n)
   .map(w -> w.window().toList())
   .toList()
);

生产

[[1, 2], [2, 3], [3, 4]]

int n = 3;

System.out.println(
Seq.of(1, 2, 3, 4)
   .window(0, n - 1)
   .filter(w -> w.count() == n)
   .map(w -> w.window().toList())
   .toList()
);

生产

[[1, 2, 3], [2, 3, 4]]

这是一篇关于它是如何工作的博客文章.

免责声明:我为jOOλ背后的公司工作



3> John McClean..:

另一个选项cyclops -react建立在jOOλ的Seq接口(和JDK 8 Stream)之上,但简单反应构建了并发/并行性(如果这对您很重要 - 通过创建Streams of Futures).

你可以使用Lukas强大的窗口函数和任何一个库(因为我们扩展了令人敬畏的jOOλ),但也有一个滑动算子,我认为在这种情况下简化了事情并且适合在无限流中使用(即它不消耗流,但在它们流过时缓冲值).

使用ReactiveSeq,它看起来像这样 -

ReactiveSeq.of(1, 2, 3, 4)
           .sliding(2)
           .forEach(System.out::println);

使用LazyFutureStream 可能看起来像下面的示例 -

 LazyFutureStream.iterate(1,i->i+1)
                 .sliding(3,2) //lists of 3, increment 2
                 .forEach(System.out::println);

在cyclops-streams StreamUtils类中还提供了用于在java.util.stream.Stream上创建滑动视图的Equivalant静态方法.

       StreamUtils.sliding(Stream.of(1,2,3,4),2)
                  .map(Pair::new);

如果您想直接使用每个滑动视图,可以使用返回List Transformer的slidingT运算符.例如,要为每个滑动视图中的每个元素添加一个数字,然后将每个滑动窗口减少为我们可以执行的元素之和: -

        ReactiveSeq windowsSummed = ReactiveSeq.fromIterable(data)
                                                        .slidingT(3)
                                                        .map(a->a+toAdd)
                                                        .reduce(0,(a,b)->a+b)
                                                        .stream();

免责声明:我为独眼巨人反应后的公司工作

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有