네 줄 요약
- 매개값으로 넘길 땐 람다식을 통해 작성한다.
- filter()를 통해 조건에 맞는 요소를 구별할 수 있다.
- map()과 flatMap()을 통해 요소의 타입이나 개수를 바꿀 수 있다.
- 객체 요소의 정렬을 위해선 해당 클래스에 Comparable을 구현하거나 Comparator의 리턴값을 매개값으로 넘겨준다.
반복자
반복자에는 외부 반복자와 내부 반복자가 있습니다.
외부 반복자의 경우 컬렉션의 요소를 반복적으로 바깥으로 가져와서 처리하며,
내부 반복자의 경우 처리 방법(람다식)을 컬렉션 내부로 주입시켜 요소를 반복 처리합니다.
외부 반복자
for 문과 Iterator는 컬렉션의 요소를 바깥쪽으로 반복해서 가져오는 외부 반복자입니다.
Set 컬렉션의 iterator() 메소드를 통해 외부 반복자 Iterator를 얻을 수 있습니다.
Iterator는 Set에 담긴 객체를 가져오고 제거하는 메소드를 제공합니다.
hasNext() : 가져올 객체가 있으면 true, 없으면 false
next() : 컬렉션의 객체 하나를 가져옴
remove() : next()로 가져온 객체를 Set에서 제거
내부 반복자
내부 반복자 Stream은 Iterator와 비슷한 반복자이지만, 다음과 같은 특징이 있습니다.
1) 내부 반복자이므로 처리 속도가 빠르고 병렬 처리에 효과적
2) 람다식으로 다양한 요소 처리를 정의
3) 중간 처리와 최종 처리를 수행하도록 파이프라인 형성
아래는 해당 코드의 스트림 파이프라인입니다.
리소스로부터 스트림 얻기
스트림은 주로 컬렉션 혹은 배열을 통해 얻습니다.
또한 리소스 별 스트림 구현 객체를 얻는 다양한 메소드가 있습니다.
컬렉션 리소스
자료 구조 : List / Set
변수 이름 : list / set
list.stream() : 오리지널 스트림
set.parallelStream() : 오리지널(병렬 처리) 스트림
배열 리소스
변수 타입 : T[ ] / int[ ] / long[ ] / double[ ] (T는 객체 타입)
변수 이름 : arrT / arrInt / arrLong / arrDouble
Arrays.stream(arrT) : 오리지널 스트림
Arrays.stream(arrInt) : IntStream
Arrays.stream(arrLong) : LongStream
Arrays.stream(arrDouble) : DoubleStream
int 범위 리소스
변수 타입 : int / long
변수 이름 : a, b / c, d
IntStream.range(a) : a부터 시작하는 IntStream
IntStream.rangeClosed(a, b) : a부터 b까지의 IntStream
LongStream.range(c) : c부터 시작하는 LongStream
LongStream.rangeClosed(c, d) : c부터 d까지의 LongStream
필터링
필터링은 스트림 파이프라인에서 중간 처리를 담당하는 역할을 합니다.
필터링 메소드에는 distinct()와 filter()가 있습니다.
distinct( )
distinct() 메소드는 스트림의 중복된 요소를 제거합니다.
filter( )
filter() 메소드는 말그대로 조건을 통해 요소를 필터링합니다.
매개 값으로 넘겨지는 Predicate가 true인 경우만 통과할 수 있습니다.
Predicate는 함수형 인터페이스로 boolean 타입의 test()라는 추상 메소드를 가집니다.
해당 메소드의 매개변수로는 다음과 같이 네 가지 타입이 선언될 수 있습니다.
test(T t) : 객체 T를 조사
test(int value) : int 값을 조사
test(long value) : long 값을 조사
test(double) : double 값을 조사
아래 예제에서는 이름 List에서 중복된 이름을 제거하고, 성이 '홍'인 이름만 필터링합니다.
매핑
매핑은 스트림의 요소들을 다른 요소로 변환하는 역할을 수행합니다.
map( ) / mapTo___( )
두 매핑 메소드의 매개변수 타입은 Function에 정의된 타입으로 변환합니다.
Function은 apply() 라는 추상 메소드를 가지는 함수형 인터페이스입니다.
apply() 메소드 및 넘겨주는 매개변수의 타입에는 객체<T>, int, long, double 등이 있습니다.
map(Function<T, R>) : T → R
mapToInt(ToIntFunction<T>) : T → int
mapToObj(LongFunction<U>) : int → U
mapToDouble(IntToDoubleFunction) : int → double
아래 예제에서는 Student 스트림을 Student의 int 타입 필드인 score 스트림으로 변환합니다.
기본 타입 간의 변환 혹은 기본 타입 요소를 래퍼(Wrapper) 객체 요소로 변환할 땐 간편화 메소드를 사용할 수도 있습니다.
asLongStream() : int → long
asDoubleStream() : int → double / long → double
boxed() : int → Integer / long → Long / double → Double
아래 예제에서는 int 배열을 통해 스트림을 획득하고 이를 실수 스트림으로 변환하고,
기본 타입 스트림을 래퍼 스트림으로 변환합니다.
flatMap( ) / faltMapTo___( )
두 매핑 메소드는 하나의 요소를 복수 개의 요소들로 변환한 새로운 스트림을 리턴합니다.
매개값으로 넘겨받은 특정 객체나 값을 스트림으로 변환합니다.
flatMap(Function<T, Stream<R>>) : T → Stream<R>
faltMap(IntFunction<IntStream>) : int → IntStream
faltMapToDouble(Function<T, DoubleStream>) : T → DoubleStream
다음 예제에서는 문장 스트림을 단어 스트림으로 변환하고, 문자열 숫자 목록 스트림을 숫자 스트림으로 변환합니다.
정렬
sorted() 메소드를 통해 요소를 오름차순 혹은 내림차순으로 정렬합니다.
기본형인 int, long, double은 각각의 래퍼 클래스에서 Comparable을 구현하고 있어 별도의 조치없이 정렬이 가능합니다.
하지만 스트림의 요소가 객체일 경우,
1) 해당 객체 클래스에 Comparable을 구현하거나
2) 비교자(Comparator)를 람다식을 통해 제공해서 정렬합니다.
Comparable
Comparable은 추상 메소드 compareTo(T o)를 가진 인터페이스입니다.
compareTo() 메소드는 매개변수로 객체를 한 개만 받는 것이 특징입니다.
내림차순 정렬은 sorted()의 매개값으로 Comparator.reverseOrder()를 넘겨주면 됩니다.
* this는 현재 객체, other는 비교 대상 객체
this < other : 음수 리턴
this > other : 양수 리턴
this == other : 0 리턴
아래 예시에서는 Student 객체의 score 필드를 기준으로 오름차순으로 정렬합니다.
Comparator
Comparator는 추상 메소드 compare(T o1, T o2)를 가진 인터페이스입니다.
compare() 메소드는 매개변수로 객체를 두 개 받는 것이 특징입니다.
o1 < o2 : 음수 리턴
o1 > o2 : 양수 리턴
o1 == o2 : 0 리턴
아래 예시에서는 Student 객체의 score 필드를 기준으로 내림차순으로 정렬합니다.
Integer.compare() 메소드를 보면 삼항 연산자를 통해 -1(음수), 0, 1(양수)을 return하고 있기 때문에 아래와 같이 표현할 수도 있습니다.
.sorted((s1, s2) -> s1.score - s2.score)
위와 같이 Comparator 구현체를 람다식으로 넘기는 방식은 List.sort()에서도 동일하게 사용 가능합니다.
또한 객체를 오름차순으로 정렬할 땐 IntelliJ에선 다음과 같은 방법을 추천합니다.
.sorted(Comparator.comparingInt(student -> student.score))
'Spring-Java > Java' 카테고리의 다른 글
Optional 클래스 (2) | 2024.04.05 |
---|---|
스트림(Stream)_최종 처리 기능 (0) | 2024.04.05 |
익명 객체와 람다식(lambda) (0) | 2024.04.03 |
Day10_class 예제 (0) | 2023.08.28 |
Day09_Overloading, 정적변수, for/each (0) | 2023.08.28 |