【发布时间】:2015-12-04 04:42:29
【问题描述】:
我正在寻找一种方法来实现非终端分组操作,这样内存开销就会最小。
例如,考虑 distinct()。在一般情况下,它别无选择,只能收集所有不同的项目,然后才将它们向前传输。但是,如果我们知道输入流已经排序,则操作可以“即时”完成,使用最少的内存。
我知道我可以使用迭代器包装器为迭代器实现这一点,并自己实现分组逻辑。有没有更简单的方法来使用流 API 来实现这一点?
--编辑--
我找到了一种滥用 Stream.flatMap(..) 来实现此目的的方法:
private static class DedupSeq implements IntFunction<IntStream> {
private Integer prev;
@Override
public IntStream apply(int value) {
IntStream res = (prev != null && value == prev)? IntStream.empty() : IntStream.of(value);
prev = value;
return res;
}
}
然后:
IntStream.of(1,1,3,3,3,4,4,5).flatMap(new DedupSeq()).forEach(System.out::println);
哪些打印:
1
3
4
5
经过一些更改,相同的技术可用于任何类型的内存高效序列分组流。无论如何,我不太喜欢这个解决方案,我一直在寻找更自然的东西(例如映射或过滤的工作方式)。此外,我在这里违反合同,因为提供给 flatMap(..) 的函数是有状态的。
【问题讨论】:
-
您总是可以
.filter(someSet::add),但是您是否尝试过将这种解决方案的性能与普通的distinct()进行比较?另外,您说“在一般情况下”,但如果Stream是ORDERED,确切地说(或更准确地说,它的底层@ 987654328@) -
@fge:我不确定那里有任何优化。代码: IntStream.range(0, 100000000).distinct().forEach(x->{});尽管底层 Spliterator 报告自己是 ORDERED,但内存不足。
-
你试过
.forEachOrdered()吗? -
DISTINCT和SORTED都有。但是 - 查看 jdk8 代码 - IntStream 实现没有使用.distinct()中的任何一个。似乎是基于引用的流。 -
@the8472:我猜重要的特征是SORTED,我的例子中生成的流有它。
标签: java java-8 java-stream