프로그래밍 언어/Java

Stream이란? - 스트림의 종류와 생성 방법 (JAVA)

제이온 (Jayon) 2021. 1. 5.

안녕하세요? 코딩중독입니다.

 

저번 시간에는 스트림의 개념과 특징에 대해서 살펴보았습니다. 오늘은 스트림의 종류는 어떤 것이 있고, 어떻게 스트림을 생성하는지 설명하겠습니다.

 

 

Stream의 종류

java.util.stream 패키지에는 다양한 스트림 API들이 존재합니다. 패키지 내용을 보면 BaseStream 인터페이스를 부모로 해서 자식 인터페이스들이 상속 관계를 이루고 있습니다.

 

BaseStream 인터페이스에는 모든 스트림에서 사용할 수 있는 추상 메소드들이 존재할 뿐 코드에서 직접적으로 사용하지는 않습니다. 코드에 직접적으로 사용하는 것은 자식 인터페이스로는, Stream, IntStream, LongStream, DoubleStream이 있습니다. 그리고 이 중에서 Stream만 객체 요소를 처리합니다.

 

 

Stream을 생성하는 방법

(1) 컬렉션으로부터 스트림 얻기

컬렉션으로는 주로 List를 쓰는데 리스트를 정의하고, 내장된 메소드인 stream()을 이용하면 됩니다.

 

만약, 학생 객체를 저장하는 studentList를 정의하였다면, 아래와 같이 스트림을 얻어올 수 있습니다.

 

 

Stream<Student> stream = studentList.stream();

 

 

그리고 정의한 stream을 이용하여 여러 가지 중간 처리나 최종 처리 작업을 하면 됩니다. 또한, 여기서 studentList.stream()과 같이 처음 얻어온 스트림을 오리지널 스트림이라고 부릅니다.

 

 

(2) 배열로부터 스트림 얻기

배열도 컬렉션에서 스트림을 얻어오는 것과 비슷합니다. 이번에는 학생의 이름을 저장하는 nameArr이 있다고 합시다. 그렇다면, 아래와 같이 배열로부터 스트림을 얻어올 수 있습니다.

 

 

Stream<String> stream = Stream.of("a", "b", "c"); // 가변 인자

 

IntStream stream = IntStream.of(1, 2, 3); // 가변 인자

 

Stream<String> stream = Arrays.stream(nameArr);

 

첫 번째는 가변 인자를 사용하는 것입니다. Stream.of() 메소드를 통해 즉석으로 원하는 값을 집어 넣음으로써 스트림을 생성할 수 있습니다.

 

두 번쨰는 Arrays.stream() 메소드를 이용하여 스트림을 얻어오면 됩니다. 간단하죠?

 

 

(3) 숫자 범위로부터 스트림 얻기

위와 같이 컬렉션이나 배열을 정의하여 스트림을 얻어올 수도 있지만, 단순하게 1 ~ 100까지의 정수가 담긴 스트림을 얻고 싶을 때는 range() 또는 rangeClosed() 메소드를 사용하면 됩니다.

 

range()는 [a, b)로 끝 구간이 열린 구간이지만, rangeClosed()는 [a, b]로 끝 구간이 닫힌 구간인 차이입니다.

 

 

IntStream stream = IntStream.rangeClosed(1, 100);

 

 

위와 같이 컬렉션이나 배열 없이도 바로 1 ~ 100까지의 정수가 담긴 스트림을 얻어올 수 있습니다.

 

 

(4) 빈 스트림 얻기

일단 빈 스트림만 선언해 놓고 싶을 경우에는 아래 처럼 소스코드를 작성하시면 됩니다.

 

 

Stream<String> stream = Stream.empty();

 

 

당연하게도 Stream의 타입은 어떤 것을 쓰셔도 상관 없습니다.

 


(5) 람다식으로 스트림 생성하기 - iterate()

iterate() 메소드는 for문과 비슷한 구조를 갖는데, 매개 변수로 초기값, Predicate<T>, UnaryOperator<T>를 사용합니다. 여기서 Predicate<T>는 선택입니다.

 

 

Stream<Integer> stream = Stream.iterate(0, n -> n + 1) // 0, 1, 2, 3, ...
.limit(5);



Stream<Integer> stream = Stream.iterate(0, n -> n < 5, n -> n + 1);

 

 

그런데, iterate() 메소드를 사용할 때 주의할 점이 있습니다. 바로, 제한 범위를 정해주어야 한다는 것입니다. 만약 이를 설정하지 않는다면, 무한정 값이 할당됩니다.

 

따라서, limit() 메소드를 사용하거나 Pridicate<T>를 이용하여 위 문제를 해결할 수 있습니다.

 

 

(6) 람다식으로 스트림 생성하기 - generate()

generate() 메소드는 매개 변수로 오직 Supplier<T>만을 갖습니다. 그런데, Supplier<T>는 매개 변수를 필요로 하지 않으므로 generate() 메소드는 결국 스트림 생성시 별도의 인수가 필요하지 않을 때 사용됩니다.

 

Random random = new Random();

 

IntStream.generate(() -> random.nextInt(45) + 1)

.limit(6);

 

 

위와 같이 로또 번호를 생성할 때 사용할 수 있겠습니다.

 

 

정리

지금까지 스트림의 종류와 생성하는 방법에 대해서 알아 보았습니다. 이제, 우리는 스트림을 정의하는 방법을 알았으니, 내장된 중간 처리와 최종 처리를 할 수 있습니다. 다음 시간부터는 이것에 대해 중점적으로 살펴보겠습니다.

 

 

참고 서적

이것이 자바다. - 저자 신용권

댓글

추천 글