상세 컨텐츠

본문 제목

[모던 자바 인 액션] 스트림 takeWhile( ), dropWhile( ), limit( ), skip( )로 슬라이싱하기

Java/Modern Java in Action

by 개발하는 정복자 2022. 6. 30. 18:09

본문

 

모던 자바 인 액션 - YES24

자바 1.0이 나온 이후 18년을 통틀어 가장 큰 변화가 자바 8 이후 이어지고 있다. 자바 8 이후 모던 자바를 이용하면 기존의 자바 코드 모두 그대로 쓸 수 있으며, 새로운 기능과 문법, 디자인 패턴

www.yes24.com


스트림 슬라이싱

1. 프레디케이트를 이용하는 방법
2. 스트림의 처음 몇 개의 요소를 무시하는 방법,
3. 특정 크기로 스트림을 줄이는 방법

다양한 방법을 이용해 효율적으로 이런 작업을 수행할 수 있다.

 

1. 프레디케이트를 이용한 슬라이싱

 

프레디케이트란?

파라미터로 값을 받아 true나 false를 반환하는 함수

 

👉🏾 TAKEWHILE

 

 

아래와 같은 요리 리스트가 있다고 하자. 320칼로리 이하의 요리를 선택해보자.

List<Dish> specialMenu = Arrays.asList(
        new Dish("seasonal fruit", true, 120, Dish.Type.OTHER),
        new Dish("prawns", false, 300, Dish.Type.FISH),
        new Dish("rice", true, 350, Dish.Type.OTHER),
        new Dish("chicken", false, 400, Dish.Type.MEAT),
        new Dish("french fries", true, 530, Dish.Type.OTHER),
        );

 

우리는 본능적으로 filter를 사용할 것이다.

List<Dish> filteredMenu = specialMenu.stream()
        .filter(dish -> dish.getCalories() < 320)
        .collect(Collectors.toList());  // seasonal fruit, prawns 목록

 

문제가 있다!?!

위 리스트는 이미 칼로리 순으로 정렬되어 있다는 사실에 주목하자. filter 연산을 이용하면 전체 스트림을 반복하면서 각 요소에 프레디케이트를 적용한다. 따라서 이미 정렬되어 있다는 사실을 이용해 320 칼로리보다 크거나 같은 요리가 나오면 반복을 중단 할 수 있다. 큰 작업에서는 성능에 직접적인 영향을 줄 수 있다.  이때 takeWhile() 을 사용하자.

 

List<Dish> slicedMenu = specialMenu.stream()
	.takeWhile(dish -> dish.getCalories() < 320)
	.collect(Collectors.toList());   // seasonal fruit, prawns 목록

 

 

👉🏾 DROPWHILE

320칼로리보다 큰 요소는 dropWhile을 사용하면 된다.

List<Dish> slicedMenu = specialMenu.stream()
	.dropWhile(dish -> dish.getCalories() < 320)
	.collect(Collectors.toList());  // rice, chicken, french fries 목록

 

dropWhile과 takeWhile은 정반대의 작업을 수행한다. dropWhile은 프레디케이트가 처음으로 거짓이 되는 지점까지 발견된 요소를 버린다. 프레디케이트가 거짓이 되면 그 지점에서 작업을 중단하고 남은 모든 요소를 반환한다. dropWhile은 무한한 남은 요소를 가진 무한 스트림에서도 동작한다.

 


2. 스트림 축소

주어진 값 이하의 크기를 갖는 새로운 스트림을 반환하는 limit(n) 메서드를 지원한다.
정렬되어 있으면 최대 요소 n개를 반환할 수 있다.
Set처럼 정렬되지 않은 스트림에도 limit을 사용할 수 있다.
소스가 정렬되어 있지 않았다면 limit의 결과도 정렬되지 않은 상태로 반환된다.

 

💻 300칼로리 이상의 세 요리를 리스트로 추출하기 👇🏾

List<Dish> dishes = specialMenu.stream()
	.filter(dish -> dish.getCalories() > 300)
	.limit(3)
	.collect(Collectors.toList());  // rice, chicken, french fries 목록

 

출처: Modern Java in Action

 

요소 건너뛰기

 

skip(n)은 처음 n개 요소를 제외한 스트림을 반환한다. 
n개 이하의 요소를 포함하는 스트림에서는 빈 스트림이 반환된다.

 

List<Dish> menu = Dish.getDishes();
        
List<Dish> dishes = menu.stream()
	.filter(d -> d.getCalories() > 300) 
	.skip(2)
	.collect(Collectors.toList());

 

출처: Modern Java in Action

관련글 더보기

댓글 영역