2014-03-30 4 views
36

현재 우리는 자바 8 Stream.concat을 다음 있습니다 :Java 8에는 스트림의 varags에서 작동하는 Stream.concat이 부족합니까?

public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b); 

내가 Stream<? extends T>의 가변 인자를 가지고 어떤 버전이없는 이유에 놀란다? 이 서명의 가변 인자를 사용할 수 있다면

Stream<Integer> resultStream = Stream.concat(stream1, Stream.concat(stream2, Stream.of(element))) 
     .filter(x -> x != 0) 
     .filter(x -> x != 1) 
     .filter(x -> x != 2); 

:

은 현재 내가 코드처럼 작성했습니다

Stream<Integer> resultStream = Stream.concat(
       stream1, 
       stream2, 
       Stream.of(element) 
     ) 
     .filter(x -> x != 0) 
     .filter(x -> x != 1) 
     .filter(x -> x != 2); 
:

public static <T> Stream<T> concat(Stream<? extends T>... streams); 

가 그럼 난으로 훨씬 더 명확하게 쓸 수

모든 종류의 중첩 된 Stream.concat 호출없이.

또는 제공되지 않는 다른 이유가 있습니까?
나는 그런 이유로 생각할 수 없다. 어쨌든 지금은 varargs 호출 작업을 끝내기 때문이다.

+0

당신이 스레드를 통과 할 수 있습니다 -> http://mail.openjdk.java.net/pipermail/lambda-dev/2013-July/010647.html –

답변

39

그냥 flatMap 그것을 :

당신의 예에서
public static void main(final String[] args) throws Exception { 
    final Stream<String> stream1 = /*some stream*/ 
    final Stream<String> stream2 = /*some stream*/ 
    final Stream<String> stream3 = /*some stream*/ 
    final Stream<String> stream4 = /*some stream*/ 
    final Stream<String> stream5 = /*some stream*/ 

    final Stream<String> stream = Stream.of(stream1, stream2, stream3, stream4, stream5).flatMap(Function.identity()); 
} 

:

Stream<Integer> resultStream = Stream.of(stream1, stream2, Stream.of(element)) 
     .flatMap(identity()) 
     .filter(x -> x != 0) 
     .filter(x -> x != 1) 
     .filter(x -> x != 2); 
+0

참고 : 이 솔루션은 무한한 스트림을 단축하지 않습니다! 자세한 내용은 여기를 참조하십시오. https://stackoverflow.com/a/48192709/907576 – radistao

+0

또는 [assylias] (https://stackoverflow.com/a/22743697/2071828)로 생각해보십시오. –

+0

글쎄, 그 대답에 의해 정확히 혼란 스러웠다. 그래서 나는 그 시험을 만들었다. – radistao

25

수집 a message in the thread linked by @RohitJain에서 :

Stream.of(s1, s2, s3, ...) 
    /* .parallel() if you want*/ 
    .reduce(Stream::concat) 
    .orElseGet(Stream::empty); 
+2

+1. 이 게시물은 스트림 중 하나가 무한하다면 'flatMap' 솔루션이 작동하지 않음을 나타냅니다. –

+2

필자는 'flatMap' 버전에서 자세한 정보를 얻을 수 있었지만이 버전은 훨씬 자세한 정보를 제공합니다 (어떤 일이 일어나는지 알아야 함). 작동하고 수동으로 10 스트림을 연결하는 것보다 낫습니다.하지만 기본적으로 기능이없는 이유를 알 수 없습니다. – skiwi

+0

@BoristheSpider 나는 그 글을 잘못 읽은 것 같아요. 그것은 '후자'가이 해결책을 가리키는 findFirst'와 같은 연산에도 s1이 무한하다면 후자는 실패 할 것이라고 말한다. 'flatMap' 버전이 실제로 안전한 접근법 인 것 같습니다. – Gili

0

SO, 집계 답변 of.flatMap()of.reduce().orElseGet() 대 : of.flatMap 처리 할 수없는 무한한 시내 s 일 때 of.reduce() - 할 수 있습니다. 아래의 시험 예를 참조하십시오

@RunWith(JUnit4.class) 
public class StreamConcatTest { 

@Rule 
public Timeout globalTimeout = Timeout.seconds(3); 

private static final Random randomSupplier = new Random(System.currentTimeMillis()); 

private Stream<Stream<Integer>> mergedStream; 

@Before 
public void setUp() throws Exception { 
    Stream<Integer> infinite = Stream.concat(
      Stream.of(1, 2, 3, 4, 5), 
      Stream.generate(randomSupplier::nextInt) 
    ); 

    Stream<Integer> finite1 = Stream.of(100, 101, 102, 103); 
    Stream<Integer> finite2 = Stream.of(222, 333, 444, 555); 

    mergedStream = Stream.of(infinite, finite1, finite2); 
} 

@Test 
public void of_flatMap_FAILS_BY_TIMEOUT() throws Exception { 
    Stream<Integer> streamToTest = mergedStream 
      .flatMap(i -> i); 

    assertThat(streamToTest 
        .skip(3) 
        .findFirst() // this should break infinite stream, but can't 
        .orElse(-1), 
      is(4)); 
} 

@Test 
public void of_reduce_SUCCESS() throws Exception { 
    Stream<Integer> streamToTest = mergedStream 
      .reduce(Stream::concat) 
      .orElseGet(Stream::empty); 

    assertThat(streamToTest 
        .skip(3) 
        .findFirst() // this really breaks infinite stream 
        .orElse(-1), 
      is(4)); 
} 
} 
+0

반면에'Stream.concat()'의 문제는 성능이 좋지 않거나'StackOverflowError'가 될 수 있다는 것입니다 많은 양의 스트림을 처리 할 때. 이것은 [Javadocs] (https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#concat-java.util.stream)의 구현 노트로도 언급됩니다. Stream-java.util.stream.Stream-). 그래서 기본적으로 솔루션은 연결하려는 스트림의 양과 스트림 중 하나가 무한한 경우 실제로 다릅니다. – g00glen00b

관련 문제