A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

java8自定义收集器

案例:接收参数int n,并将前n个自然数分为质数和非质数。


第一种方式自定义收集器第一步:实现收集器接口,重写收集器方法,以及定义业务逻辑方法


  • package com.java8.CustomCollector;







  • import java.util.*;



  • import java.util.function.*;



  • import java.util.stream.Collector;







  • public class PrimeNumbersCollector implements Collector<Integer,Map<Boolean,List<Integer>>,Map<Boolean,List<Integer>>>{







  •     /**



  •      * 作用:创建结果容器



  •      * @return



  •      */



  •     @Override



  •     public Supplier<Map<Boolean,List<Integer>>> supplier() {



  •         return () -> new HashMap<Boolean,List<Integer>>(){{



  •             put(true,new ArrayList<>());



  •             put(false,new ArrayList<>());



  •         }};



  •     }







  •     /**



  •      * 作用:将元素添加到结果容器



  •      * @return



  •      */



  •     @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);



  •         };



  •     }







  •     /**



  •      * 对结果容器进行转换



  •      * @return



  •      */



  •     @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;



  •         };



  •     }







  •     /**



  •      * 作用:当为并行流时,合并两个或多个结果容器



  •      * @return



  •      */



  •     @Override



  •     public Function<Map<Boolean,List<Integer>>,Map<Boolean,List<Integer>>> finisher() {



  •         return Function.identity();



  •     }







  •     /**



  •      * 作用:返回一个不可变的 Characteristics 集合



  •      * @return



  •      */



  •     @Override



  •     public Set<Characteristics> characteristics() {



  •         return Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));



  •     }







  •     /**



  •      * 行为参数化方法,



  •      * @param list



  •      * @param p



  •      * @param <A>



  •      * @return



  •      */



  •     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;



  •     }







  •     /**



  •      * 主要判断逻辑()判断是否是质数



  •      * @param primes



  •      * @param candidate



  •      * @return



  •      */



  •     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);



  •     }



  • }



第二步:应用方法与java8内置收集归约函数做对比


  • package com.java8.CustomCollector;







  • import java.util.List;



  • import java.util.Map;



  • import java.util.stream.IntStream;







  • import static java.util.stream.Collectors.partitioningBy;







  • public class Test {



  •     public static void main(String[] arg){



  •         long fastest  = Long.MAX_VALUE;



  •         for(int i = 0; i < 10 ;i++){



  •             long start = System.nanoTime();



  •             partitionPrimes(1000000);



  •             long duration = (System.nanoTime() - start) / 1000000;



  •             if (duration < fastest ) fastest = duration;



  •         }



  •         System.out.println("Fastest execution done in " + fastest +" msecs");







  •         for(int i = 0; i < 10 ;i++){



  •             long start = System.nanoTime();



  •             partitionPaimesWithCustomCollector(1000000);



  •             long duration = (System.nanoTime() - start) / 1000000;



  •             if (duration < fastest ) fastest = duration;



  •         }



  •         System.out.println("CustomCollector Fastest execution done in " + fastest +" msecs");



  •     }











  •     /**



  •      * 自定义收集器调用



  •      * @param n



  •      * @return



  •      */



  •     public static  Map<Boolean,List<Integer>> partitionPaimesWithCustomCollector(int n){



  •         return IntStream.rangeClosed(2,n).boxed().collect(new PrimeNumbersCollector());



  •     }











  •     /**



  •      *采用系统分区函数



  •      * @param n



  •      * @return



  •      */



  •     public static Map<Boolean,List<Integer>> partitionPrimes(int n){



  •         return IntStream.rangeClosed(2,n).



  •                 boxed().



  •                 collect(partitioningBy(candidate -> isPrime(candidate)));



  •     }











  •     /**



  •      *判断是否为质数



  •      * @param candidate



  •      * @return



  •      */



  •     public static boolean isPrime(int candidate){



  •         int candidateRoot = (int)Math.sqrt((double)candidate);



  •         return IntStream.rangeClosed(2,candidateRoot).boxed().noneMatch(i -> candidate % i == 0);



  •     }







  • }



函数输出(提高了55%)

Fastest execution done in 865 msecs

CustomCollector Fastest execution done in 382 msecs



第二种方式实现自定义收集器把实现核心逻辑的三个函数传给collect方法的重载版本来获得同样的结果。


  • package com.java8.CustomCollector;







  • import java.util.ArrayList;



  • import java.util.HashMap;



  • import java.util.List;



  • import java.util.Map;



  • import java.util.function.Predicate;



  • import java.util.stream.IntStream;







  • import static java.util.stream.Collectors.partitioningBy;







  • public class Test {



  •     public static void main(String[] arg){



  •         long fastest  = Long.MAX_VALUE;



  •         for(int i = 0; i < 10 ;i++){



  •             long start = System.nanoTime();



  •             partitionPaimesWithCustomCollector(1000000);



  •             long duration = (System.nanoTime() - start) / 1000000;



  •             if (duration < fastest ) fastest = duration;



  •         }



  •         System.out.println("CustomCollector Fastest execution done in " + fastest +" msecs");



  •     }















  •     /**



  •      * 自定义收集器调用



  •      * @param n



  •      * @return



  •      */



  •     public static  Map<Boolean,List<Integer>> partitionPaimesWithCustomCollector(int n){



  •         return IntStream.rangeClosed(2,n).boxed().collect(



  •                 ()->new HashMap<Boolean,List<Integer>>(){{



  •                     put(true,new ArrayList<>());



  •                     put(false,new ArrayList<>());



  •                 }},



  •                 (acc,candidate) ->{



  •                     acc.get(isPrime(acc.get(true)



  •                             ,candidate)



  •                     ).add(candidate);



  •                 },



  •                 (map1,map2) ->{



  •                     map1.get(true).addAll(map2.get(true));



  •                     map1.get(false).addAll(map2.get(false));



  •                 });



  •     }



  •     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 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);



  •     }



  • }




收获:可以自己需要的时候开发自己的收集器 (虽然比较麻烦),可以用于追求性能的优化


2 个回复

倒序浏览
回复 使用道具 举报
~(。≧3≦)ノ⌒☆
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马