Phi*_*ßen 14 java java-8 java-stream
将流转换为滑动窗口的推荐方法是什么?
例如,在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
Run Code Online (Sandbox Code Playgroud)
在Guava中,我发现只有Iterators#partition,它是相关的但没有滑动窗口:
final Iterator<List<Integer>> partition =
Iterators.partition(IntStream.range(1, 5).iterator(), 3);
partition.forEachRemaining(System.out::println);
-->
[1, 2, 3]
[4]
Run Code Online (Sandbox Code Playgroud)
Tag*_*eev 17
API中没有这样的功能,因为它支持顺序和并行处理,并且很难为任意流源提供滑动窗口函数的有效并行处理(即使是高效的并行处理对很难,我实现了它,所以我知道).
但是,如果您的源是List快速随机访问,您可以使用subList()方法来获得所需的行为,如下所示:
public static <T> Stream<List<T>> sliding(List<T> 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));
}
Run Code Online (Sandbox Code Playgroud)
类似的方法实际上可以在我的StreamEx库中找到:参见StreamEx.ofSubLists().
还有一些其他第三方解决方案不关心并行处理,并使用一些内部缓冲区提供滑动功能.例如,质子包StreamUtils.windowed.
Luk*_*der 11
如果您愿意使用第三方库而不需要并行性,那么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()
);
Run Code Online (Sandbox Code Playgroud)
生产
[[1, 2], [2, 3], [3, 4]]
Run Code Online (Sandbox Code Playgroud)
和
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()
);
Run Code Online (Sandbox Code Playgroud)
生产
[[1, 2, 3], [2, 3, 4]]
Run Code Online (Sandbox Code Playgroud)
免责声明:我为jOOλ背后的公司工作
另一个选项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);
Run Code Online (Sandbox Code Playgroud)
使用LazyFutureStream 可能看起来像下面的示例 -
LazyFutureStream.iterate(1,i->i+1)
.sliding(3,2) //lists of 3, increment 2
.forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)
在cyclops-streams StreamUtils类中还提供了用于在java.util.stream.Stream上创建滑动视图的Equivalant静态方法.
StreamUtils.sliding(Stream.of(1,2,3,4),2)
.map(Pair::new);
Run Code Online (Sandbox Code Playgroud)
如果您想直接使用每个滑动视图,可以使用返回List Transformer的slidingT运算符.例如,要为每个滑动视图中的每个元素添加一个数字,然后将每个滑动窗口减少为我们可以执行的元素之和: -
ReactiveSeq<Integer> windowsSummed = ReactiveSeq.fromIterable(data)
.slidingT(3)
.map(a->a+toAdd)
.reduce(0,(a,b)->a+b)
.stream();
Run Code Online (Sandbox Code Playgroud)
免责声明:我为独眼巨人反应后的公司工作
如果您想将 Scala 持久集合的全部功能引入 Java,您可以使用Vavr库(以前称为 Javaslang)。
// this imports List, Stream, Iterator, ...
import io.vavr.collection.*;
Iterator.range(1, 5).sliding(3)
.forEach(System.out::println);
// --->
// List(1, 2, 3)
// List(2, 3, 4)
Iterator.range(1, 5).sliding(2, 3)
.forEach(System.out::println);
// --->
// List(1, 2)
// List(4)
Iterator.ofAll(javaStream).sliding(3);
Run Code Online (Sandbox Code Playgroud)
你不仅可以使用Iterator,这也适用于几乎任何其他Vavr集合:Array,Vector,List,Stream,Queue,HashSet,LinkedHashSet,TreeSet,...
(Javaslang 2.1.0-alpha 概述)
免责声明:我是 Vavr(以前称为 Javaslang)的创建者。
| 归档时间: |
|
| 查看次数: |
7406 次 |
| 最近记录: |