Java 정리 3. Stream API
※이 글은 Java SE 8 기준으로 작성되었습니다.
Stream API이란
Stream API 는 데이터 집합(Source)들의 처리(Operation)를 위한 API임.
java.util.stream패키지로 제공되어 있으며, 자바에서는 흔히 함수형 인터페이스(람다식)를 이용하여 만듬.
Stream이라는 용어에 대하여 혼동이 있을 수 있는데, 파일(File)이나 네트워크에서 사용하는 java.io.InputStream이나 OutputStream같은 Stream과는 별개임.
데이터집합(Source) : 어떤 처리를 할 데이터로서 시작데이터임. 데이터의 집합이므로 Array나 Set등 데이터구조에서 사용가능
중간조작(파이프라인): Source가 들어오면 그 데이터들을 처리하는 곳임. 처리는 여러번 몇번이고 나열할 수 있음.
종단조작(Result): 처리가 끝난 결과값임.
Stream API 종류
-
BaseStream 인터페이스
기본적인 Stream임. 밑 네 개의 Stream 인터페이스들의 부모 인터페이스
-
Stream< T >
제네릭 인터페이스로서 타입 설정 가능
-
IntStream
정수형을 가진 Stream
-
LongStream
Long타입을 가진 Stream
-
DoubleStream
Double타입을 가진 Stream
BaseStream을 제외한 Stream들은 filter이나 map, sorted등 데이터를 다루는 유용한 추상메서드를 가지고 있음.
자주 사용하는 메서드
IntStream 타입으로 기술되어 있습니다.
-
filter
public static void main(String... args) { int[] array = {1, 2, 3, 4, 5}; IntStream is = Arrays.stream(array); is.filter(value -> value % 2 == 0) // 짝수만 필터처리 .forEach(value -> System.out.print(value + " ")); // 2 4 출력 }
IntStream filter(IntPredicate) 는 Predicate 함수형 인터페이스를 받아서 boolean값을 리턴하여, 그에 해당하는 데이터만 처리하는 메서드임.
위 코드에서는 짝수일 경우만 값을 출력
-
map
public static void main(String... args) { int[] array = {1, 2, 3, 4, 5}; IntStream is = Arrays.stream(array); is.map(operand -> operand * operand) // 각 값을 제곱 .forEach(value -> System.out.print(value + " ")); // 1 4 9 16 25 출력 }
IntStream map(IntUnaryOperator) 는 IntUnaryOperator 함수형 인터페이스를 받아서 리턴되는 int형 값으로 출력하는 메서드
위 예제에서는 각 값의 제곱을 출력
-
sorted
public static void main(String... args) { int[] array = {2, 4, 3, 1, 5}; IntStream is = Arrays.stream(array); is.sorted() // 정렬 .forEach(value -> System.out.print(value + " ")); // 1 2 3 4 5 출력 }
IntStream sorted() 는 들어온 값들을 정렬함
-
peek
public static void main(String... args) { int[] array = {2, 4, 3, 1, 5}; IntStream is = Arrays.stream(array) .sorted() // 정렬 .peek(value -> System.out.println(value + "A")) // 1A 2A 3A 4A 5A .filter(value -> value > 3) .peek(value -> System.out.println(value + "B")) // 4B, 5B .map(operand -> operand * operand) .peek(value -> System.out.println(value + "C")); //16C, 25C System.out.println(is.count()); // 2 (개수 출력) // 출력 결과 // 1A // 2A // 3A // 4A // 4B // 16C // 5A // 5B // 25C // 2 }
IntStream peek(IntConsumer) 는 Consumer를 받는 메서드로 forEach와 비슷한 메서드처럼 보이는데, forEach는 종단처리로 마지막에 실행하고, peek는 intStream을 리턴하는 중간처리임.
종단처리가 없으면 결국 실행되지도 않음. 위 코드에서는 count() 메서드를 이용하여 종단처리를 했기 때문에 peek메서드에서 출력이 된 것. count같은 종단 처리가 없을 경우에는 실행 되지 않는다.
출력결과를 보면 순서가 뒤죽박죽인것을 알 수 있는데 중간처리라서 순서대로 작동하지도 않음.