Java 8流允许我们在按任意约束进行分组时收集元素。例如:
Map<Type, List<MyThing>> grouped = stream
.collect(groupingBy(myThing -> myThing.type()));
然而,这样做的缺点是必须完全读取流,因此不可能对grouped
上的未来操作进行惰性评估。
有没有办法进行分组操作以获得Stream<Tuple<Type, Stream<MyThing>>>
之类的内容?在概念上是否可以在不评估整个数据集的情况下以任何语言懒惰地分组?
答案 0 :(得分:4)
懒惰分组的概念并没有多大意义。根据定义,分组意味着预先选择组以避免搜索每个键的所有元素的开销。 “懒惰分组”看起来像这样:
List<MyThing> get(Type key) {
source.stream()
.filter(myThing -> myThing.type().equals(key))
.collect(toList());
}
如果您希望将迭代推迟到您知道需要它时,或者如果您想避免缓存分组映射的内存开销,那么这非常好。但是,如果不提前迭代,就无法优化选择过程。
答案 1 :(得分:1)
应该只对一个流进行操作(调用中间或终端流操作)。例如,这排除了&#34;分叉&#34;流,其中相同的源提供两个或多个管道,或多个遍历同一个流。
取自以下文件:
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
所以我认为没有办法在不消耗它并创建新流的情况下拆分它。
答案 2 :(得分:0)
我认为这没有意义,因为从一个惰性流Tuple<Type, Stream<MyThing>>
的一个分区流(Stream<Tuple<Type, Stream<MyThing>>>
)读取可能会在其他分区中产生任意大量的消耗内存。
E.g。考虑自然顺序中的正整数的惰性流,并将它们按其最小的素因子分组。然后从分区流的最后一个接收元素中读取将在之前接收的流中产生越来越多的整数。
答案 3 :(得分:0)
在概念上是否可以在不评估整个数据集的情况下以任何语言懒惰地进行分组?
不,如果不检查整个数据集或保证数据中可利用的模式,则无法正确分组整个数据集。例如,我可以将前10,000个整数分组为偶数奇数,但是我不能懒得将偶数组合成偶数组10,000个整数。
至于以非终端方式进行分组......这似乎不是一个好主意。从概念上讲,流上的分组函数应该返回多个流,就像它分支不同的流一样,而Java 8不支持它。
如果您确实希望使用本机Stream方法进行非终端分组,则可能会滥用已排序的方法。给它一个分类器,以不同的方式处理组,但将组内的所有元素视为相等,并且你最终会得到group1,group2,group3等。这不会给你懒惰的评价,但它正在分组。