JAva 8 in action:第六章学習:データストリーム収集データ、カスタムコレクタ質量数

6976 ワード

前の章では、ストリームの使用方法を学び、この章では、ストリームの他の知識点を深く学び続けます.
接続文字列の使用joining()
String str=menu.stream()
                   .map(Dish::getName)
                   .collect(joining());
    
String str2=menu.stream()
                    .map(Dish::getName)
                    .collect(joining(","));

reducing工場方法
//     ,          
    //     , dish        int
    //     ,BinaryOperator,  
    int totalCalories=menu.stream().collect(reducing(0,Dish::getCalories,(i,j) -> i+j));

//     
    Optional maxCalories=menu.stream().collect(
                               reducing((d1,d2) -> d1.getCalories() >d2.getCalories() ?d1:d2));

グループはCollectors.groupingByを使用
 Map> dishesByType=menu.stream()                                          
                                               .collect(Collectors.groupingBy(Dish::getType));
    
    System.out.println(dishesByType);

public enum CaloricLevel {
    Diet,Normal,Fat
}       

Map> dishesByCaloricLevel=menu.stream().collect(
                                Collectors.groupingBy( dish -> {
                                    if (dish.getCalories()<=400)  return CaloricLevel.Diet;
                                    else if(dish.getCalories()<=700) return CaloricLevel.Normal;
                                    else return CaloricLevel.Fat;
                                }));

マルチレベルパケット:上記のコードを改善します.タイプと熱でグループ化します.
Map>> dishesByCaloricLevel=menu.stream().collect(
                                Collectors.groupingBy(Dish::getType,
                                Collectors.groupingBy( dish -> {
                                    if (dish.getCalories()<=400)  return CaloricLevel.Diet;
                                    else if(dish.getCalories()<=700) return CaloricLevel.Normal;
                                    else return CaloricLevel.Fat;
                                })));

インポートクラスを覚えています:import static java.util.stream.Collectors.;Collectorsは書かなくてもいいです.*
分類クエリDishの各typeの合計.
Map typesCount=menu.stream().
                            collect(groupingBy(Dish::getType,counting()));

各グループの中で最も熱量の高いDishを検索
Map mostCaloricByType=menu.stream()
                                            .collect(groupingBy(Dish::getType,
                                            collectingAndThen(//      
                                            maxBy(Comparator.comparing(Dish::getCalories)), Optional::get)));

分類要約:
    //        
    Map totalCaloriesByType=menu.stream().collect(groupingBy(Dish::getType,
            summingInt(Dish::getCalories)));
    System.out.println(totalCaloriesByType);

パーティションpartitioningBy
Map> partitionedMenu2=menu.stream().collect(partitioningBy(dish -> dish.getCalories()>=300));
    System.out.println(partitionedMenu2);

質量数と非質量数の判断
public  static boolean isPrime(int candidate){
    int candidateRoot=(int) Math.sqrt((double)candidate);//  
    return IntStream.rangeClosed(2, candidateRoot)
                    .noneMatch(i ->candidate%i==0);
}

public static Map> partitionPrimes(int n){
    return IntStream.rangeClosed(2, n).boxed().collect(partitioningBy(candidate -> isPrime(candidate)));
}

カスタムコレクタ100以内の質量数を探す
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.IntStream;

public class PrimeCollector implements Collector>, Map>> {

@Override
public Supplier>> supplier() {
    return () -> new HashMap>(){{
        put (true,new ArrayList());
        put (false,new ArrayList());
    }};
}

@Override
public BiConsumer>, Integer> accumulator() {
    return (Map> acc,Integer candidate) -> {
        acc.get(isPrime(acc.get(true), candidate))
        .add(candidate);
    };
}

@Override
public BinaryOperator>> combiner() {
    return (Map> map1,
            Map> map2) ->{
                map1.get(true).addAll(map2.get(true));
                map1.get(false).addAll(map2.get(false));
                return map1;
            };
}

@Override
public Function>, Map>> finisher() {
    return Function.identity();
}

@Override
public Set characteristics() {
    return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
}

public  static boolean isPrime(List primes,int candidate){
    int candidateRoot=(int) Math.sqrt((double)candidate);//  
    return takeWhile(primes, i -> i<= candidateRoot)
            .stream().noneMatch(p -> candidate%p==0);
}

public staticListtakeWhile(Listlist,Predicatep){
int i=0;
for (A item : list) {
if (!p.test(item)) {
return list.subList(0, i);
}
i++;
}
return list;
}
}
public static Map> partitionPrimesWithCustomCollector(int n){
return IntStream.rangeClosed(2, n).boxed().collect(new PrimeCollector());
}

上のコードの代わりに簡単に書く
public static Map> findPrimes(int n){
    return Stream.iterate(2, i -> i+1).limit(n)
        .collect(
                () -> new HashMap>(){{
                    put(true, new ArrayList());
                    put(false, new ArrayList());
                }},
                (acc,candidate ) -> {
                    acc.get( PrimeCollector.isPrime(acc.get(true), candidate))
                    .add(candidate);
                },
                (map1,map2 ) -> {
                    map1.get(true).addAll(map2.get(true));
                    map2.get(false).addAll(map2.get(false));
                }
                );
}

今日はここまでです.