JAVA 🎻
[JAVA] 스트림 활용하기
minl741
2023. 3. 4. 15:32
모던 자바 인 액션 5장을 보고 정리한 내용입니다.
1. 필터링, 스트림 슬라이싱
고유 요소 필터링
distinct
- 고유 요소로 이루어진 스트림을 반환하는 메서드
- 즉, 중복한 값들은 반환하지 X
- 고유 여부는 스트림에서 만든 객체의 hashCode, equals로 결정
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(i -> i % 2 ==0)
.distinct()
.forEach(System.out::println);
// 출력
// 2
// 4
스트림 슬라이싱
takeWhile
- 무한 스트림을 포함한 모든 스트림에 프레디케이트를 적용해 스트림을 슬라이스 가능
takeWhile과 filter의 차이?
filter 메서드가 전체 스트림에 대한 Predicate를 판단하는 반면
takeWhile은 Predicate가 false를 반환하는 순간 나머지 요소를 전부 버린다.
따라서 무한 스트림에도 슬라이스가 가능한 이유는 takeWhile은 false가 반환되면 더이상 실행이 멈춰지는 것
즉, 스트림에서 중간 요소를 조건에 따라 끊을 수 있기 때문입니다.
dropWhile
- takeWhile과 반대의 작업을 수행
- 프레디케이트가 처음으로 거짓이 되는 지점까지 발견된 요소를 버림
- 프레디케이트가 거짓이 되면 그 지점에서 작업을 중단하고 남은 모든 요소를 반환
스트림 축소
limit
- 주어진 값 이하의 크기를 갖는 새로운 스트림을 반환하는 메서드
요소 건너뛰기
skip
- 처음 n개의 요소를 제외한 스트림을 반환하는 메서드
2. 매핑
특정 객체에서 특정 데이터를 선택하는 작업
map
- 함수를 인수로 받는 메서드로
- 함수는 각 요소에 적용되며 함수를 적용한 결과가 새로운 요소로 매핑
List<String> word = Arrays.asList("Modern", "Java", "In", "Action");
List<Integer> wordLengths = word.stream()
.map(String::length)
.collect(toList());
스트림 평면화
map 메서드에서 반환받은 스트림의 형식과 우리가 원하는 문자열의 형식이 다를 때
→ Stream<String[]>을 받았지만 Stream<String>이 필요할 때
flatMap 사용하기
- 평면화가 가능해짐
평면화란?
다차원 배열(2차원 배열, 3차원 배열, 4차원 배열 등)을 1차원 배열 또는 2차원 배열로 변환하는 과정을 의미한다.
예를 들어, 2차원 배열 {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}를 평면화하면 {1, 2, 3, 4, 5, 6, 7, 8, 9}가 됩니다. 이처럼, 다차원 배열의 요소를 모두 하나의 배열로 나열하는 것이 1차원 평면화입니다.
특정 속성이 데이터 집합에 있는지 여부를 검색하는 처리
3. 검색과 매칭
매칭
anyMatch()
- 프레디케이트가 적어도 한 요소와 일치하는지 확인
- 불리언을 반환하므로 최종 연산
if(menu.stream.anyMatch(Dish::isVegetarian)) {
System.out.println("Thre menu is vegetarian friendly!");
}
allMatch()
- 프레디케이트가 스트림의 모든 요소와 일치하는지 검사
boolean isHealthy = menu.stream()
.allMatch(dish -> dish.getCalories() < 1000);
noneMatch()
- allMatch()와 반대 연산
- 주어진 프레디케이트와 일치하는 요소가 없는지 검사
위 세 메서드는 쇼트서킷을 사용
- 쇼트 서킷
- 표현식에서 하나라도 거짓이라는 결과가 나오면 나머지 표현식의 결과와 상관없이 전체 결과도 거짓
검사
스트림 파이프라인은 내부적으로 단일과정으로 실행될 수 있도록 최적화됨
→ 즉, 쇼트서킷을 이용해서 결과를 찾는 즉시 실행을 종료
findFirst
- 논리적인 아이템 순서가 정해져 있는 경우 첫 번째 요소 반환
findAny
- 현재 스트림에서 임의의 요소를 반환
리듀싱
모든 스트림 요소를 처리해서 값으로 도출하는 것
요소의 합 reduce
- 기존의 코드
int sum = 0;
for (int x : numbers) {
sum += x;
}
- reduce를 사용한 코드
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
- reduce(초기값 0, 두 요소를 조합해서 새로운 값을 만드는 BinaryOperator<T>)
최대값과 최솟값
//최대값
Optional<Integer> max = numbers.stream().reduce(Integer::max);
//최솟값
Optional<Integer> min = numbers.stream().reduce(Integer::min);