간단한 Stream API 사용 예제
Java 8 이전의 코드
List<Dish> lowCaloricDishes = new ArrayList<>();
for(Dish dish : menu) {
if(dish.getCalories() < 400) {
lowCaloricDishes.add(dish)
}
}
Collections.sort(lowCaloricDishes, new Comparator<Dish>() {
public int compare(Dish dish1, Dish dish2) {
return Integer.compare(dish1.getCalories(), dish2.getCalories());
};
});
List<String> lowCaloriesDishesName = new ArrayList<>();
for(Dish dish : lowCaloricDishes) {
lowCaloriesDishesName.add(dish.getName());
}
Java 8 이후의 코드
// 기본적인 사용
List<String> lowCaloricDishesName =
menu.stream()
.filter(d -> d.getCalories() < 400)
.sorted(comparing(Dish::getCalories))
.map(Dish::getName)
.collect(toList());
// 아래처럼 parallelStream 사용하면 멀티코어 아키텍처에서 병렬로 실행 가능
List<String> lowCaloricDishesName =
menu.parallelStream()
.filter(d -> d.getCalories() < 400)
.sorted(comparing(Dish::getCalories))
.map(Dish::getName)
.collect(toList());
Java 8 Stream API의 특징
Stream 이란
Stream의 주요 특징
파이프라이닝
내부 반복
Stream을 활용한 예시 코드
List<String> threeHighColoricDishNames = menu
.stream()
.filter(dish -> dish.getColories() > 400)
.map(Dish::getName)
.limit(3) // MySQL LIMIT처럼 사용됨(선착순 3개만 반환)
.toList();
// 마지막 Collect 연산으로 파이프라인 형성할 수 있도록 스트림 반환
// 마지막에 Collect 호출하기 전까지는 어떠것도 선택/출력되지 않음
컬렉션과 스트림의 차이
영화를 예제로 컬렉션과 스트림의 차이
외부 반복과 내부 반복
외부 반복
컬렉션 인터페이스를 사용하여 사용자가 직접 요소를 반복하는 것
내부 요소를 하나하나 가져와서 처리하는 방식
병렬성을 이용하기 위해서는 개발자가 직접 관리
예) for문을 활용한 반복
예시 코드
// for-each 루프를 이용하는 외부반복
List<String> names = new ArrayList<>();
for(Dish dish : menu) {
names.add(dish.getName());
}
// 내부적으로 숨겨졌던 반복자를 사용한 외부반복
List<String> names = new ArrayList<>();
Iterator<String> menu.iterator();
while(iterator.hasNext()) {
Dish dish = iterator.next();
names.add(dish.getName());
}
내부 반복
반복을 알아서 처리하고 결과 스트림값을 어딘가에 저장해줌
내부 반복을 사용하면 투명하게 병렬로 처리하거나 최적화된 순서로 처리 가능
예시 코드
// 스트림을 활용한 내부반복(반복을 알아서 처리)
List<String> names = menu
.stream()
.map(Dish::getName)
.toList();
스트림 연산 구분
코드에서의 중간 연산과 최종 연산