java8 in action:第六章学习:数据流收集数据,自定义收集器找质数

上一章学习如何使用流,这一章继续深入学习流的一些别的知识点。

连接字符串的使用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<Dish> maxCalories=menu.stream().collect(
                               reducing((d1,d2) -> d1.getCalories() >d2.getCalories() ?d1:d2));

分组使用Collectors.groupingBy

 Map<Dish.Type, List<Dish>> dishesByType=menu.stream()                                          
                                               .collect(Collectors.groupingBy(Dish::getType));
    
    System.out.println(dishesByType);

public enum CaloricLevel {
    Diet,Normal,Fat
}       

Map<CaloricLevel, List<Dish>> 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<Dish.Type, Map<CaloricLevel,List<Dish>>> 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<Dish.Type, Long> typesCount=menu.stream().
                            collect(groupingBy(Dish::getType,counting()));

查询每组中热量最高的Dish

Map<Dish.Type, Dish> mostCaloricByType=menu.stream()
                                            .collect(groupingBy(Dish::getType,
                                            collectingAndThen(//第二个收集器
                                            maxBy(Comparator.comparing(Dish::getCalories)), Optional::get)));

分类汇总:

    //查询每一类的总和
    Map<Dish.Type, Integer> totalCaloriesByType=menu.stream().collect(groupingBy(Dish::getType,
            summingInt(Dish::getCalories)));
    System.out.println(totalCaloriesByType);

分区partitioningBy

Map<Boolean, List<Dish>> 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<Boolean ,List<Integer>> 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<Integer, Map<Boolean,List<Integer>>, Map<Boolean,List<Integer>>> {

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

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

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

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

@Override
public Set<java.util.stream.Collector.Characteristics> characteristics() {
    return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
}

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

public static<A> List<A> takeWhile(List<A> list,Predicate<A> p){
    int i=0;
    for (A item : list) {
        if (!p.test(item)) {
            return list.subList(0, i);
        }
        i++;
    }
    return list;
}
}

public static Map<Boolean, List<Integer>> partitionPrimesWithCustomCollector(int n){
    return IntStream.rangeClosed(2, n).boxed().collect(new PrimeCollector());
}

写一个简单地代替上面的代码

public static Map<Boolean, List<Integer>> findPrimes(int n){
    return Stream.iterate(2, i -> i+1).limit(n)
        .collect(
                () -> new HashMap<Boolean,List<Integer>>(){{
                    put(true, new ArrayList<Integer>());
                    put(false, new ArrayList<Integer>());
                }},
                (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));
                }
                );
}

今天就到这里了。

    原文作者:墙角的牵牛花
    原文地址: https://www.jianshu.com/p/e56c4f501217
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞