合并两个流

2022-09-04 21:42:25

我正在尝试实现一种方法,根据值的a将值合并为两个。StreamComparator

我有一种方法可以做到这一点,我迭代流并将值插入到一个中,但我无法弄清楚如何制作一个延迟计算的版本(许多流操作的方式),所以它也可以处理无限流。Stream.Builder

我想要它做的就是对输入数据执行单个合并传递,而不是对流进行排序(实际上,流很可能是无序的;这种无序需要保留)。

static Stream<E> merge(Stream<E> first, Stream<E> second, Comparator<E> c)

我怎么能像这样懒惰地合并两个流?

如果我用两个s作为输入和一些作为输出来执行此操作,这将相当简单:QueueConsumer

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 ...

正如你所看到的,这不仅仅是,因为(a)你不能对无限流进行排序,并且(b)即使你可以对流进行排序,它也不会给出所需的结果。concat(first,second).sort()


答案 1

您需要实现 一个 ,而不是通过 。为此,您甚至可以只经历一个 ,因为它是一个相当连续的操作。轻轻地使用番石榴,SpliteratorStream.BuilderIterator

return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
    Iterators.mergeSorted(
      Arrays.asList(stream1.iterator(), stream2.iterator()),
      comparator),
    Spliterator.ORDERED),
  false /* not parallel */ );

答案 2

Iterables.mergeSorted() from Guava

public static <T> Iterable<T> mergeSorted(Iterable<? extends Iterable<? extends T>> iterables,
                Comparator<? super T> comparator)