lambda表达式:Collectors源码解析

Collectors 源码解析

对于Collectors静态工厂类来说,其实现一共分为两种情况

  1. 通过内置CollectorImpl来实现
  2. 通过reducing方法来实现,reducing方法本身又是通过CollectorImpl来实现的

Collectors工厂类来说 里面大多是方法都是利用下游收集器的5个方法进行部分改进从而生成一个新的Collector收集器

mapping

	/*
		将流中数据执行mapper映射,映射的数据存到传过来的收集器当中
		 Set<String> collect = list.stream()
		 .collect(Collectors.mapping(x -> x + ",", Collectors.toSet()));
        //等价上面
        list.stream().map(x -> x + ",").collect(Collectors.toList());
        System.out.println(collect);
该方法本质是替换参数downstream下游收集器的的accumulator()方法 实现转换返回上游收集器
	*/
  public static <T, U, A, R>
    Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
                               Collector<? super U, A, R> downstream) {
         /*
         获取传过来参数的 downstream.accumulator() 行为操作
         如 toList方法的List::add
         */
        BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
        //传过去执行参数的行为操作 (Supplier<Set<T>>) HashSet::new
        return new CollectorImpl<>(downstream.supplier(),
        //该行为 将流中数据执行mapper.apply(t)的结果存到r(中间容器的)里 (x, y) -> x.add(y);
        (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)),
        //返回并行的函数行为 (left, right) -> { left.addAll(right); return left; },
        downstream.combiner(),
        //返回收集器参数的finisher行为 x->x
        downstream.finisher(),
        //CH_UNORDERED_ID
        downstream.characteristics());
    }

在这里插入图片描述

collectingAndThen

	/*
	中间转换 将收集器的到数据在进行转换,返回转换后的值
	 List<String> people
     = people.stream().collect(collectingAndThen(toList(),
     	Collections::unmodifiableList));
	*/
    public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
                                                                Function<R,RR> finisher) {
        Set<Collector.Characteristics> characteristics = downstream.characteristics();
        /*
        为啥去除IDENTITY_FINISH特性?
        应为 实例CollectorImpl 必须要调用finisher 如果强制类型转换了
        就不会调用finisher
        */
        if (characteristics.contains(Collector.Characteristics.IDENTITY_FINISH)) {
            if (characteristics.size() == 1)
                characteristics = Collectors.CH_NOID;
            else {
                characteristics = EnumSet.copyOf(characteristics);
                characteristics.remove(Collector.Characteristics.IDENTITY_FINISH);
                characteristics = Collections.unmodifiableSet(characteristics);
            }
        }
        return new CollectorImpl<>(downstream.supplier(),
                                   downstream.accumulator(),
                                   downstream.combiner(),
              //改行为是将收集器参数的最终返回值当finisher参数的值出入 返回最终的转换的最终结果
              //具体看之前andThen详解
                                   downstream.finisher().andThen(finisher),
                                   characteristics);
    }

summingInt

/*
	汇总流中数据 返回收集器
*/
 public static <T> Collector<T, ?, Integer>
    summingInt(ToIntFunction<? super T> mapper) {
        return new CollectorImpl<>(
        		/中间容器数组
                () -> new int[1],
                //将流中数据t累加 
                (a, t) -> { a[0] += mapper.applyAsInt(t); },
                //合并每个数组的值 返回值
                (a, b) -> { a[0] += b[0]; return a; },
                //返回最终类型
                a -> a[0], CH_NOID);
    }

在这里插入图片描述

reducing

	/*
	创建收集器
	*/
   public static <T> Collector<T, ?, T>
    reducing(T identity, BinaryOperator<T> op) {
        return new CollectorImpl<>(
        	//生成新的中间容器
                boxSupplier(identity),
                //数据累加
                (a, t) -> { a[0] = op.apply(a[0], t); },
                //并行流收集各线程流的数据
                (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
                //返回最终的结果
                a -> a[0],
                //该收集器特性
                CH_NOID);
    }
      @SuppressWarnings("unchecked")
    private static <T> Supplier<T[]> boxSupplier(T identity) {
        return () -> (T[]) new Object[] { identity };
    }

groupingBy(串行)

调用重载方法
在这里插入图片描述
在这里插入图片描述
doc

  • 返回一个收集器,该收集器对T类型的输入元素执行级联的“group by”操作,根据分类函数对元素进行分组,然后使用指定的下游收集器对与给定key关联的Value执行汇聚操作。收集器生成的映射是使用提供的工厂函数创建的。
  • 分类函数将元素映射到某个键类型K。下游收集器对类型T的元素进行操作并生成类型D的结果。生成的收集器生成Map<K,D>。
  • 例如,要计算每个城市中按城市名称排序的人的姓氏集,请执行以下操作:
    Map<City, Set> namesByCity
    = people.stream().collect(groupingBy(Person::getCity, TreeMap::new,
    mapping(Person::getLastName, toSet())));
/*
具体大方向
	T:流中元素
	K:分类器返回的结果类型(根据谁分组 谁的类型)
	D: 被分组的数据类型
	A:下游累加器中间结果类型
	M:最终返回结果类型
	?:表示调用者不关注中间结果生成类型是什么
	如  该方法返回的 值M的类型就是 Function<Map<K, A>, M>
	
*/
  public static <T, K, D, A, M extends Map<K, D>>
    Collector<T, ?, M> groupingBy(//key类型
    							  Function<? super T, ? extends K> classifier,
    							  //中间结果类型
                                  Supplier<M> mapFactory,
                                  //下游收集器
                                  Collector<? super T, A, D> downstream) {
         //获取下游收集器的supplier方法 (Supplier<List<T>>) ArrayList::new生成中间容器
        Supplier<A> downstreamSupplier = downstream.supplier();
       	// 获取下游收集器的accumulator方法 List::add得到累加器对象
        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
        //将classifier行为执行结果做key 中间容器结果做value 封装成map生成中间累加器对象
        //将流中数据填充到A当中
        BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
        	//将流中元素执行classifier行为得到的结果做key
            K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
            //computeIfAbsent方法返回指定的键应key的容器对象(方法详解如下)
            /*如果m map中key没有对应值会将 key和 downstreamSupplier.get()
            得到的结果组合put到m(Map<K, A> m) map当中
            此时就生成一个新的BiConsumer<Map<K, A>, T> 累加器
            */
            A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
            /*
            将流中数据累加到新的BiConsumer<Map<K, A>, T>容器当中
            此时是将累加器中的A值进行赋值
            */
            downstreamAccumulator.accept(container, t);
        };
        //并行合并多线程执行结果得到最终返回结果数据 该行为作为上游收集器的combiner()行为
        BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner());
        /*
        将传过来的HashMap::new得到的中间结果类型强转成 上游需要的中间结果容器
        mapFactory.get方法肯定返回此时中间结果类型
        此时上下文已经定义好了中间结果类型所以能强转成功
        */
        @SuppressWarnings("unchecked")
        Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory;
		//根据特性分别实现收集器 如果设置了IDENTITY_FINISH 无需给定finisher
        if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
            return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID); 
        }
        else {//反之
            @SuppressWarnings("unchecked")
            Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
            Function<Map<K, A>, M> finisher = intermediate -> {
            //通过map.replaceAll方法执行downstreamFinisher.apply行为
            //得到的结果替换到该key的value值当中
                intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
                @SuppressWarnings("unchecked")//强转成返回结果
                M castResult = (M) intermediate;
                return castResult;
            };
            return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
        }
    }

Map.computeIfAbsent()

在这里插入图片描述在这里插入图片描述

Map.replaceAll

在这里插入图片描述
示例
在这里插入图片描述

groupingByConcurrent(并行无序)

类似groupingBy
在这里插入图片描述

partitioningBy 分区

  public static <T, D, A>
    Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
                                                    Collector<? super T, A, D> downstream) {
         //获取下游的accumulator() 如toLIst的List::add
        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
        //通过行为判断将流中元素分别存到Partition的forTrue或forFalse当中
        //此时Partition默认设置为k v的形式
        BiConsumer<Partition<A>, T> accumulator = (result, t) ->
                downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t);
        //多线程合并线程的数据
        BinaryOperator<A> op = downstream.combiner();
        BinaryOperator<Partition<A>> merger = (left, right) ->
                new Partition<>(op.apply(left.forTrue, right.forTrue),
                                op.apply(left.forFalse, right.forFalse));
        Supplier<Partition<A>> supplier = () ->
                new Partition<>(downstream.supplier().get(),
                                downstream.supplier().get());
        //如果IDENTITY_FINISH特性 中间和最终结果容器相同直接返回                        
        if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
            return new CollectorImpl<>(supplier, accumulator, merger, CH_ID);
        }
        else {
            Function<Partition<A>, Map<Boolean, D>> finisher = par ->
            //Partition 最终返回类型就是 Map<Boolean, D> 类型
                    new Partition<>(downstream.finisher().apply(par.forTrue),
                                    downstream.finisher().apply(par.forFalse));
            return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
        }
    }

Partition

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值