Stream API (四)-- 实现Colletor接口自定义收集器

Java 8的Stream的Collect方法用于收集处理过的“流”,将“流”转成其他对象。Collect方法接收一个Collector接口实现,除了Java API中的Collectors工厂提供的toList、toSet、groupingBy、partitionBy等实现以外,还可以通过实现Collector方法自定义收集器。

和Collectors.toList()方法相同效果的自定义实现:

/**
 * Collector<T,A,R>
 * T是流中要收集的类型
 * A是累加器的类型
 * R是收集操作得到的类型(不一定和A相同)
 */
public class ToListCollector<T> implements Collector<T,List<T>,List<T>> {
    @Override
    //supplier方法提供一个空的累加器,用于数据处理过程中的收集
    public Supplier<List<T>> supplier() {
        return ArrayList::new;
    }

    @Override
    //accumulator方法提供归约操作,即数据收集的具体操作
    public BiConsumer<List<T>, T> accumulator() {
        return List::add;
    }

    @Override
    //combiner方法提供合并并行处理的结果集的操作
    public BinaryOperator<List<T>> combiner() {
        return (list1, list2) -> {
          list1.addAll(list2);
          return list1;
        };
    }

    @Override
    //finisher提供对结果容器的最终转化,即从A->R
    public Function<List<T>, List<T>> finisher() {
        return Function.identity();
    }

    @Override
    //characteristics用于设定优化参数,参数有:UNORDERED、CONCURRENT、IDENTITY_FINISH
    public Set<Characteristics> characteristics() {
        return Collections.unmodifiableSet(EnumSet.of(Characteristics.CONCURRENT,Characteristics.IDENTITY_FINISH));
    }
}

 

自定义收集器实现将前n个自然数按质数和非质数分区:

public class PrimeNumbersCollector 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<>());
            put(false,new ArrayList<>());
        }};
    }

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

    @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<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 Map<Boolean, List<Integer>> partitionPrimesWithCustomCollector(int n) {
        return IntStream.rangeClosed(2, n).boxed().collect(new PrimeNumbersCollector());
    }
    
}

也可以只在一个方法内实现:

    /**
     * 也可以直接在collect方法中写,第一个参数相当于supplier方法,
     * 第二个参数相当于accumulator方法,
     * 第三个参数相当于combiner方法
     * @param n
     * @return
     */
    public Map<Boolean, List<Integer>> partitionPrimesWithCustomCollector
            (int n) {
        return IntStream.rangeClosed(2, n).boxed()
                .collect(
                        () -> new HashMap<Boolean, List<Integer>>() {{
                            put(true, new ArrayList<Integer>());
                            put(false, new ArrayList<Integer>());
                        }},
                        (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));
                        });
    }

 

转载于:https://my.oschina.net/pierrecai/blog/886836

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值