2014-04-09 4 views
7

값을 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 :

1, 2, 2, 2, 3, 3, 1, 2, 2, 2, 2, 3 

예 :

merge(
    Stream.of(1, 2, 3, 1, 2, 3), 
    Stream.of(2, 2, 3, 2, 2, 2), 
    Comparator.naturalOrder() 
); 

이 시퀀스를 생성 할 스트림을 반환

은 코멘트를 해결하기 위해, 몇 가지 예를 들어 입력 및 결과는 2 :

merge(
    Stream.iterate(5, i->i-1), 
    Stream.iterate(1, i->i+1), 
    Comparator.naturalOrder() 
); 
(A)을 할 수없는 종류의 무한 스트리밍하기 때문에,이 단지 concat(first,second).sort()하지 않습니다 당신이 볼 수 있듯이

1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0, -1 ... 

:

는 (잘 INT_MAX + 5 항목) 시퀀스를 생성 할 스트림을 무한을 반환 그리고 (b) 스트림을 정렬 할 수있는 경우에도 원하는 결과를 얻지 못합니다.

+1

질문을 모두 말하지 않으면 원본 스트림이 정렬되지 않기 때문에 실제로 병합 할 수 없습니다. 즉, 스트림 1에서 읽어야 할 요소가 동일한 스트림에서 다른 요소보다 먼저 효과적으로 공급되어야하는지, 스트림 2에서 동일한 문제가 있는지 미리 알 수 없다는 것을 의미합니다. 솔루션을 둘 다 삼키는 것과는 별도로 존재할 것을 심각하게 기대 했습니까? 정렬? – fge

+3

'Stream.concat (first, second) .sorted (c); '외에도 많은 일을 할 수 있을지 모르겠다. ... – assylias

+0

나는이 일이 무엇을하는지 정말로 이해하지 못한다. @AJMansfield, 당신이 기대하는 것의 입력과 출력 예제를 줄 수 있습니까? 당신이 의미하는 바에 따라 이것은 희망이 없을 수도 있지만 말할 수는 없습니다. 스트림을 "병합"한다는 것은 무엇을 의미합니까? 정렬 된 가져 오기에서 병합과 같은 병합이 가능하다면 수행 할 수 있습니다. –

답변

6

Stream.Builder을 통과하는 대신 Spliterator을 구현해야합니다. 이를 위해 상당히 순차적 인 작업이기 때문에 Iterator을 통과 할 수도 있습니다. 구아바 사용하기 가볍게,

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

뭔가 빠뜨린 것이 틀림 없지만 이것이 OP 문제를 어떻게 해결하는지 보지 못합니까? – fge

+0

OP에서 업데이트 된 설명이 주어지면 이는 사실 올바른 대답입니다. –

+2

'Spliterator.ORDERED'가되어서는 안됩니까? –