•
스트림은 자바 8 API에 새로 추가된 기능으로 스트림을 이용하면 선언형으로 컬렉션 데이터를 처리할 수 있다.
•
스트림이 데이터 컬렉션 반복을 처리하는 기능이라고 생각하자. 스트림을 사용하면 멀티스레드 코드를 구현하지 않아도 데이터를 투명하게 병렬로 처리할 수 있다.
•
스트림의 병렬 처리는 이후 자세하게 설명하므로 우선은 스트림이 어떤 유용한 기능을 제공하는지 확인하자.
•
다음 예제는 저칼로리의 요리명을 반환하고 칼로리를 기준으로 요리를 정렬하는 자바 7 코드다.
List<Dish> lowCaloricDishes = new ArrayList<>();
for(Dish dish: menu) {
if(dish.getCalroies() < 400) {
lowCaloricDishes.add(dish);
}
}
Collections.sort(lowCaloricDishes, new Comparator<Dish>() {
public int compare(Dish dish1, Dish dish2) {
return Integer.compare(dish1.getCalroies(), dish2.getCalroies());
}
});
List<String> lowCaloricDishesName = new ArrayList<>();
for(Dish dish: lowCaloricDishes) {
lowCaloricDishesName.add(dish.getName());
}
Java
복사
•
다음은 최신 코드다.
List<String> lowCaloricDishesName = menu.stream()
.filter(d -> d.getCalories() < 400)
.sorted(comparing(Dish::getCalroies))
.map(Dish::getName)
.collect(toList());
Java
복사
◦
stream()을 parallelStream()으로 변경하면 이 코드를 멀티코어 아키텍처에서 병렬로 실행하게 할 수 있다.
◦
parallelStream()을 호출했을 때 정확히 어떤 일이 일어날까? 얼마나 많은 스레드가 사용되는 걸까? 얼마나 성능이 좋을까? 이는 7장에서 설명한다.
◦
일단은 스트림의 새로운 기능들이 소프트웨어공학적으로 다음과 같은 다양한 이득을 준다는 것만 기억하자.
▪
선언형으로 코드를 구현할 수 있다. 즉 루프와 if 조건문 등의 제어 블록을 사용해서 어떻게 동작을 구현할지 지정할 필요없이, 동작의 수행을 지정할 수 있다.
▪
filter, sorted, map, collect같은 여러 빌딩 블록 연산을 연결해서 복잡한 데이터 처리 파이프라인을 만들 수 있다. 여러 연산을 파이프라인으로 연결해도 여전히 가독성과 명확성이 유지된다.
◦
filter같은 연산은 고수준 빌딩 블록으로 이루어져 있으므로 특정 스레딩 모델에 제한되지 않고 자유롭게 어떤 상황에서든 사용할 수 있다.
◦
결과적으로 우리는 데이터 처리 과정을 병렬화하면서 스레드와 락을 걱정할 필요가 없다. 이 모든 것이 스트림 API 덕분이다.
◦
자바 8의 API의 특징을 다음처럼 요약할 수 있다.
▪
선언형 : 더 간결하고 가독성이 좋아진다.
▪
조립할 수 있음 : 유연성이 좋아진다.
▪
병렬화 : 성능이 좋아진다.