Java 스트림(Stream)에서 concat(a, b)은 두 개의 스트림 a와 b를 연결하여 새로운 스트림을 리턴합니다.

리턴된 새로운 스트림은 스트림 a와 b가 갖고 있는 모든 요소들을 발생시킵니다.

Stream.concat()

아래와 같이 두개의 Stream a와 b를 인자로 받습니다. 리턴 값은 a와 b가 합쳐진 새로운 Stream을 리턴합니다.

Stream<T> Stream.concat(Stream<? extends T> a, Stream<? extends T> b)

예제1. 두개의 스트림을 하나의 Stream으로 연결

아래 예제는 stream1stream2를 연결하여 새로운 스트림을 리턴합니다.

합쳐진 newStream의 요소들을 출력해보면 두개의 스트림의 모든 요소들이 출력되는 것을 볼 수 있습니다.

import java.util.stream.Stream;

public class Example {

    public static void main(String[] args) {

        Stream<Integer> stream1 = Stream.of(1, 2, 3);
        Stream<Integer> stream2 = Stream.of(4, 5, 6);

        Stream<Integer> newStream = Stream.concat(stream1, stream2);
        newStream.forEach(System.out::println);
    }
}

Output:

1
2
3
4
5
6

예제 2. 3개의 Stream을 하나의 Stream으로 연결

2개 보다 많은 Stream을 하나의 스트림으로 연결할 때는 Stream.concat()을 여러번 사용하면 됩니다.

아래 예제는 3개의 Stream을 하나의 Stream으로 연결하는 예제입니다.

import java.util.stream.Stream;

public class Example {

    public static void main(String[] args) {

        Stream<Integer> stream1 = Stream.of(1, 2, 3);
        Stream<Integer> stream2 = Stream.of(4, 5, 6);
        Stream<Integer> stream3 = Stream.of(7, 8, 9);

        Stream<Integer> newStream = Stream.concat(Stream.concat(stream1, stream2), stream3);
        newStream.forEach(System.out::println);
    }
}

Output:

1
2
3
4
5
6
7
8
9

예제 3. Stream을 합치면서 중복 요소는 제거

두개의 Stream을 합칠 때, 중복된 요소가 있어도 리턴되는 Stream에 포함됩니다.

만약 중복된 값이 있을 때, 하나의 값만 Stream에 포함되길 원한다면 distinct()를 사용하여 중복 값을 제거할 수 있습니다.

  • Stream.concat(stream1, stream2).distinct() : concat으로 리턴된 스트림에서 중복 요소 제거
  • 아래 예제는 2가 중복 요소 이고, 결과를 보면 리턴된 스트림에 2는 한개만 포함됨
import java.util.stream.Stream;

public class Example {

    public static void main(String[] args) {

        Stream<Integer> stream1 = Stream.of(1, 2, 3);
        Stream<Integer> stream2 = Stream.of(4, 2, 6);

        Stream<Integer> newStream = Stream.concat(stream1, stream2).distinct();
        newStream.forEach(System.out::println);
    }
}

Output:

1
2
3
4
6

예제 4. 병렬 Stream을 concat()으로 합치기

병렬 스트림을 concat()으로 합치고 새로운 스트림을 사용할 때, Stream에서 발생되는 요소의 순서를 보장할 수 없습니다. 아래 예제를 실행해보면 위의 예제들과 순서가 다른 것을 볼 수 있습니다.

  • parallel() : 스트림을 병렬 스트림으로 변환
import java.util.stream.Stream;

public class Example {

    public static void main(String[] args) {

        Stream<Integer> stream1 = Stream.of(1, 2, 3).parallel();
        Stream<Integer> stream2 = Stream.of(4, 5, 6).parallel();

        Stream<Integer> newStream = Stream.concat(stream1, stream2);
        newStream.forEach(System.out::println);
    }
}

Output:

4
5
6
1
2
3

순서를 보장하면서 병렬 스트림 출력

만약 병렬 스트림으로 합쳐진 스트림을 순서대로 출력하고 싶으면 forEach() 대신에 forEachOrdered()를 사용하면 됩니다.

forEach()는 병렬 스트림의 요소를 처리할 때 순서를 보장하지 않지만, forEachOrdered()는 순서를 보장합니다.

import java.util.stream.Stream;

public class Example {

    public static void main(String[] args) {

        Stream<Integer> stream1 = Stream.of(1, 2, 3).parallel();
        Stream<Integer> stream2 = Stream.of(4, 5, 6).parallel();

        Stream<Integer> newStream = Stream.concat(stream1, stream2);
        newStream.forEachOrdered(System.out::println);
    }
}

Output:

1
2
3
4
5
6