
중간 연산
최종 연산
컬렉션, 컬렉터, collect이 헷갈리지 않게 주의하기
collect
collector
collectors
Collectors.toList()
Collection
Collection은 Iterable을 상속받는 인터페이스
Collections는 Object를 상속받는 클래스
헷갈릴만두;;;;
함수형 프로그래밍
함수형 API 장점
컬렉터 장점
collect
Collectors에서 제공하는 메서드의 기능
컬렉터
ex 1) counting() 이라는 팩토리 메서드가 반환하는 컬렉터로 메뉴에서 요리 수를 계산
long howManyDishes = menu.stream().collect(Collectors.counting());
메뉴에서 칼로리 가장 높은 요리 찾기
Comparator<Dish> dishCaloriesComparator =
Comparator.comparingInt(Dish::getCalories);
Optional<Dish> mostCalorieDish = menu.stream().collect(maxBy(dishCaloriesComparator));
→ 요약 연산
Collectors 클래스
int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));
컬렉터 joining 팩토리 메서드
메뉴의 모든 요리명을 연결
String shortMenu = menu.stream().map(Dish::getName).collect(joining());
joining 메서드
하지만 결과 문자열 해석 불가
모든 컬렉터 reducing 팩토리 메서드로 정의 가능
이거 대신 특화된 컬렉터 사용이유
ex) reducing 메서드로 만들어진 컬렉터로도 모든 메뉴의 칼로리 합계 계산 가능
int totalCalories = menu.stream().collect(reducing(0, Dish::getCalories,(i,j) ->(i+j));
reducing 인수를 세개 받음
컬렉션 프레임 워크 유연성: 같은 연산도 다양한 방식으로 수행 가능
int totalCalories = menu.stream().collect(reducing(0,Dish::getCalories,Integer::sum));
자신의 상황에 맞는 최적의 해법 선택
그룹화
→ 자바 8의 함수형을 이용하면 가독성 있는 한 줄의 코드로 그룹화 구현 가능
ex) 메뉴를 그룹화 한다고 가정
고기를 포함하는 그룹, 생선을 포함하는 그룹, 나머지 그룹
Collectors.groupingBy를 이용해 쉽게 메뉴 그룹화
Map<Dish.Type, List<Dish>> dishesByType = menu.stream().collect(groupingBy(Dish::getType));
요소를 그룹화 한 다음에 결과 그룹의 요소를 조작하는 연산 필요
ex) 500칼로리 넘는 요리만 필터 가정
Map<Dish.Type, List<Dish>> caloricDishesByType = menu.stream()
.filter(dish -> dish.getCalories() > 500)
.collect(groupingBy(Dish::getType));
위 처럼 해결할 수 있지만 FISH가 사라진다는 단점
Map<Dish.Type, List<Dish>> caloricDishesByType = menu.stream()
.collect(groupingBy(Dish::getType,filtering(dish -> dish.getCalories() > 500, toList())));
Collectors.groupingBy를 이용해 항목을 다수준으로 그룹화
Map<Dish.Type, Map<CaloricLevel, List<Dish>> dishesByTypeCaloricLevel =
menu.stream().collect(groupingBy(Dish::getType, groupingBy(dish -> if(dish.getCalories() <= 400) return CaloircLevel.DIET;
else if(dish.getCalories() <= 700) return CaloricLevel.NORMAL; else return CaloricLevel.FAT;
Map<Dish.Type, Optional<Dish>> mostCaloricByType = menu.stream().collect(
groupingBy(Dish::getType, maxBy(comparingInt(Dish::getCalories))));
컬렉터 결과를 다른 형식에 적용하기
Map<Dish.Type, Dish> mostCaloricByType = menu.stream().collect(
groupingBy(Dish::getType, collectingAndThen(maxBy(comparingInt(Dish::getCalories)),Optional::get)));
collectingAndThen
중첩 컬렉터 작동 가장 외부 계층에서 안쪽으로
분할
ex) 채식주의자 친구를 저녁에 초대 가정, 모든 요리를 채식 과 채식 아닌 것으로 분류
Map<Boolean, List<Dish>> partitionedMenu = menu.stream().collect(partitioningBy(Dish::isVegetarian));
Map<Boolean, Map<Dish.Type, List<Dish>>> vegetarianDishesByType = menu.stream().collect
(partitioningBy(Dish::isVegetarian, groupingBy(Dish::getType)));
toList
Collector 인터페이스의 시그니처와 다섯 개의 메서드 정의
public interface Collector<T,A,R>{
Supplier<A> supplier();
BiConsumer<A,T> accumulator();
Function<A,R> finisher();
BinaryOperator<A> combiner();
Set<Characteristics> characteristics();
}
Supplier 메서드: 새로운 결과 컨테이너 만들기
accumulator 메서드: 결과 컨테이너에 요소 추가하기
public BiConsumer<List<T> ,T> accumulator(){
return (list, item) -> list.add(item);
}
//메서드 참조로 바꾸면 간결
public BiConsumer<List<T>, T> accumulator(){
return List::add;
}
finisher 메서드: 최종 변환값을 결과 컨테이너로 적용
public Function<List<T> , List<T>> finisher(){
return Function.identity();
}
combiner 메서드: 두 결과 컨테이너 병합
public BinaryOperator<List<T>> combiner(){
return(list1, list2) -> {
list1.addAll(list2);
return list1;
}
}
Characteristics 메서드
public class ToListCollector<T> implements Collector<T, List<T>, List<T>> {
@Override
public Supplier<List<T>> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer<List<T>, T> accumulator() {
return List::add;
}
@Override
public BinaryOperator<List<T>> combiner() {
return (list1, list2) -> {
list1.addAll(list2);
return list1;
};
}
@Override
public Function<List<T>, List<T>> finisher() {
return Function.identity();
}
@Override
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(
IDENTITY_FINISH, CONCURRENT));
}
}
음.. 이건 알아서 해보는게 .. 맞는 부분인거같음;;