모던 자바 인 액션 6장 2
2021, Mar 13
그룹화된 요소 조작
-
다음과 같은 클래스가 존재한다.
public class Dish { private final String name; private final int calories; private final Type type; public Dish(final String name, final int calories, final Type type) { this.name = name; this.calories = calories; this.type = type; } public String getName() { return name; } public int getCalories() { return calories; } public Type getType() { return type; } } public enum Type { NORMAL, DIET, FAT } public class Main { public static void main(String[] args) { List<Dish> menu = Arrays.asList( new Dish("pork", 800, Type.FAT), new Dish("beef", 700, Type.FAT), new Dish("salmon", 450, Type.NORMAL), new Dish("bean", 120, Type.DIET) ); //이곳에서 작업한다. } }
-
500 칼로리가 넘는 음식만 필터링 하기 (null Type 미포함)
Map<Type, List<Dish>> caloricDishesByType = menu.stream() .filter(dish -> dish.getCalories() > 500) .collect(Collectors.groupingBy(Dish::getType));
-
500 칼로리가 넘는 음식만 필터링 하기 (null Type 포함)
Map<Type, List<Dish>> caloricDishesByType = menu.stream() .collect(Collectors.groupingBy(Dish::getType, Collectors.filtering(dish -> dish.getCalories() > 500, Collectors.toList())));
-
다수준 그룹화
Map<Type, Map<Type, List<Dish>>> dishesByTypeCaloricLevel = menu.stream() .collect(Collectors.groupingBy(Dish::getType, Collectors.groupingBy(dish -> { if (dish.getCalories() <= 400) return Type.DIET; else if (dish.getCalories() <= 700) return Type.NORMAL; else return Type.FAT; })));
-
서브그룹으로 데이터 수집 종류별 개수 구하기
Map<Type, Long> typesCount = menu.stream() .collect(Collectors.groupingBy(Dish::getType, Collectors.counting()));
-
컬렉터 결과를 다른 형식에 적용하기, 각 서브 그룹에서 칼로리가 높은 요리 찾기
Map<Type, Dish> mostCaloricByType = menu.stream() .collect(Collectors.groupingBy(Dish::getType, Collectors.collectingAndThen( Collectors.maxBy(Comparator.comparingInt(Dish::getCalories)), Optional::get )));
분할
분할 함수라 불리는 프레디케이트를 분류 함수로 사용하는 특수한 그룹화 기능이다.
- Boolean 으로 분리하기
Map<Boolean, List<Dish>> partitionedMenu = menu.stream()
.collect(Collectors.partitioningBy(dish -> dish.getCalories() <= 400));
-
장점
- 참, 거짓 두 가지 요소의 스트림 리스트를 모두 유지한다는 것
-
참, 거짓 각각의 그룹에서 최대값 찾기
Map<Boolean, Dish> mostCaloricPartitionedByNameLength = menu.stream() .collect(Collectors.partitioningBy(dish -> dish.getName().length() < 5, Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(Dish::getCalories)) , Optional::get)));
숫자를 소수와 비소수로 분할하기
-
정수 n을 인수로 받아서 2에서 n까지의 자연수를 소수와 비소수로 나누는 프로그램
public boolean isPrime(int candidate) { return IntStream.range(2, candidate).noneMatch(i -> candidate % i == 0); }
-
소수의 대상을 주어진 수의 제곱근 이하의 수로 제한하기
public boolean isPrime(int candidate) { int candidateRoot = (int) Math.sqrt((double) candidate); return IntStream.rangeClosed(2, candidateRoot).noneMatch(i -> candidate % i == 0); }
-
소수와 비소수로 분리
public Map<Boolean, List<Integer>> partitionPrimes(int n) { return IntStream.rangeClosed(2, n).boxed().collect(Collectors.partitioningBy(candidate -> isPrime(candidate))); }