[英]Merge Two Streams
我正在尝试实现一种方法来基于值的Comparator
合并两个Stream
中的值。
我有一种方法可以做到这一点,我遍历流并将值插入到Stream.Builder
,但我无法弄清楚如何制作延迟评估版本(许多流操作的方式),所以它也可以处理无限流。
我想要它做的只是对输入数据执行一次合并传递,而不是对流进行排序(实际上,流很可能是无序的;需要保留这种无序)。
static Stream<E> merge(Stream<E> first, Stream<E> second, Comparator<E> c)
我怎样才能像这样懒惰地合并两个流?
如果我用两个Queue
作为输入和一些Consumer
作为输出来做这件事,那将是相当简单的:
void merge(Queue<E> first, Queue<E> second, Consumer<E> out, Comparator<E> c){
while(!first.isEmpty() && !second.isEmpty()
if(c.compare(first.peek(), second.peek()) <= 0)
out.accept(first.remove());
else
out.accept(second.remove());
for(E e:first)
out.accept(e);
for(E e:second)
out.accept(e);
}
但是我需要通过惰性评估和流来做到这一点。
为了解决这些评论,以下是一些示例输入和结果:
示例 1:
merge(
Stream.of(1, 2, 3, 1, 2, 3),
Stream.of(2, 2, 3, 2, 2, 2),
Comparator.naturalOrder()
);
将返回一个会产生这个序列的流:
1, 2, 2, 2, 3, 3, 1, 2, 2, 2, 2, 3
示例 2:
merge(
Stream.iterate(5, i->i-1),
Stream.iterate(1, i->i+1),
Comparator.naturalOrder()
);
将返回一个无限(嗯,一个INT_MAX + 5
项)流,它将产生序列:
1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0, -1 ...
如您所见,这不仅仅是concat(first,second).sort()
,因为(a)您无法对无限流进行排序,并且(b)即使您可以对流进行排序,它也不会给出所需的结果。
您需要实现一个Spliterator
,而不是通过Stream.Builder
。 为此,您甚至可能只是通过一个Iterator
,因为它是一个相当顺序的操作。 轻轻使用番石榴,
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
Iterators.mergeSorted(
Arrays.asList(stream1.iterator(), stream2.iterator()),
comparator),
Spliterator.ORDERED),
false /* not parallel */ );
来自番石榴的 Iterables.mergeSorted()
public static <T> Iterable<T> mergeSorted(Iterable<? extends Iterable<? extends T>> iterables,
Comparator<? super T> comparator)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.