美文网首页java8的世界Android 开发技术分享程序员
java8 in action:第六章学习:数据流收集数据,自定

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

作者: 墙角的牵牛花 | 来源:发表于2017-06-22 16:07 被阅读95次

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

    连接字符串的使用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));
                    }
                    );
    }
    

    今天就到这里了。

    相关文章

      网友评论

        本文标题:java8 in action:第六章学习:数据流收集数据,自定

        本文链接:https://www.haomeiwen.com/subject/yzbxcxtx.html