Stream API는 스트림 파이프라인을 통해 컬렉션에 대한 다양한 연산을 손쉽게 수행할 수 있도록 풍부한 내장 기능을 제공합니다. 이 API는 선언형 프로그래밍(Declarative Programming) 방식을 채택하고 있어 코드가 간결해지고 오류 발생 가능성도 크게 줄어듭니다.
Java 9에서는 Stream API에 실무에서 유용하게 활용할 수 있는 몇 가지 메서드가 새롭게 추가되었습니다.
- Stream.iterate(): 전통적인 for 루프를 대체할 수 있는 스트림 버전의 반복 메서드입니다.
- Stream.takeWhile(): 조건이 참인 동안 값을 계속 가져오는(take) while 루프와 유사한 동작을 수행합니다.
- Stream.dropWhile(): 조건이 참인 동안 값을 건너뛰는(drop) while 루프와 유사한 동작을 수행합니다.
아래 예제에서는 Stream API의 정적 메서드인 iterate(), takeWhile(), dropWhile()을 실제로 구현하여 사용하는 방법을 확인할 수 있습니다.
예제 코드
import java.util.Arrays;
import java.util.Iterator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamAPITest {
public static void main(String args[]) {
String[] sortedNames = {"Adithya", "Bharath", "Charan", "Dinesh", "Raja", "Ravi", "Zaheer"};
System.out.println("[Traditional for loop] Indexes of names starting with R = ");
for(int i = 0; i < sortedNames.length; i++) {
if(sortedNames[i].startsWith("R")) {
System.out.println(i);
}
}
System.out.println("[Stream.iterate] Indexes of names starting with R = ");
Stream.iterate(0, i -> i < sortedNames.length, i -> ++i).filter(i -> sortedNames[i].startsWith("R")).forEach(System.out::println);
String namesAtoC = Arrays.stream(sortedNames).takeWhile(n -> n.charAt(0) <= 'C')
.collect(Collectors.joining(","));
String namesDtoZ = Arrays.stream(sortedNames).dropWhile(n -> n.charAt(0) <= 'C')
.collect(Collectors.joining(","));
System.out.println("Names A to C = " + namesAtoC);
System.out.println("Names D to Z = " + namesDtoZ);
}
}
코드 설명
- Stream.iterate(0, i -> i < sortedNames.length, i -> ++i): 초기값 0부터 시작해 인덱스가 배열 길이 미만일 때까지 1씩 증가시키며 스트림을 생성합니다. 이후
filter()로 'R'로 시작하는 이름의 인덱스만 추출합니다. - takeWhile(n -> n.charAt(0) <= 'C'): 이름의 첫 글자가 'C' 이하인 동안만 요소를 가져와 'A'부터 'C'까지의 이름을 모읍니다.
- dropWhile(n -> n.charAt(0) <= 'C'): 첫 글자가 'C' 이하인 요소를 건너뛰고, 그 이후의 요소들('D'부터 'Z')을 모읍니다.
실행 결과
[Traditional for loop] Indexes of names starting with R = 4 5 [Stream.iterate] Indexes of names starting with R = 4 5 Names A to C = Adithya,Bharath,Charan Names D to Z = Dinesh,Raja,Ravi,Zaheer
실행 결과에서 볼 수 있듯이 Stream.iterate()는 기존의 전통적인 for 루프와 동일한 결과를 훨씬 간결한 코드로 얻을 수 있습니다. 또한 takeWhile()과 dropWhile()은 정렬된 데이터에서 특정 조건 범위를 나눌 때 매우 직관적으로 활용할 수 있습니다.