java8Collector

初识Collector体会Collector的强大

三个主要功能
在这里插入图片描述
java.util.stream.Collector
它的实现类
java.util.stream.Collectors

聚合

Apple

public class Apple {

    private String color;
    private long weight;

    public Apple() {
    }

    public Apple(String color, long weight) {
        this.color = color;
        this.weight = weight;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public long getWeight() {
        return weight;
    }

    public void setWeight(long weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "color='" + color + '\'' +
                ", weight=" + weight +
                '}';
    }
}

聚合

    public static void main(String[] args) {
        List<Apple> list = Arrays.asList(
                new Apple("green", 150),
                new Apple("yellow", 120),
                new Apple("green", 170));

        List<Apple> greenList = list.stream().filter(a -> a.getColor().equals("green")).collect(Collectors.toList());
        Optional.of(greenList).ifPresent(System.out::println);
        //[Apple{color='green', weight=150}, Apple{color='green', weight=170}]
    }

分组

根据颜色分组

传统做法

    /**
     * 按颜色分组
     * @param apples
     * @return
     */
    private static Map<String,List<Apple>> groupByNomal(List<Apple> apples){
        Map<String,List<Apple>> map = new HashMap<>();
        for (Apple apple : apples) {
            List<Apple> list = map.get(apple.getColor());
            if(list==null){
                list=new ArrayList<>();
                map.put(apple.getColor(),list);
            }
            list.add(apple);
        }
        return map;
    }
    Optional.of(groupByNomal(list)).ifPresent(System.out::println);
        //{green=[Apple{color='green', weight=150}, Apple{color='green', weight=170}],
        // yellow=[Apple{color='yellow', weight=120}]}

lamda 函数式编程

   private static Map<String, List<Apple>> groupByFunction(List<Apple> apples) {
        Map<String, List<Apple>> map = new HashMap<>();
        apples.parallelStream().forEach(a -> {
            List<Apple> colorList = Optional.ofNullable(map.get(a.getColor())).orElseGet(() -> {
                List<Apple> list = new ArrayList<>();
                map.put(a.getColor(), list);
                return list;
            });
            colorList.add(a);
        });
        //        map=null;   (Variable used in lambda expression should be final or effectively final)
        return map;
    }

lambda中使用外层的变量,不能在lamdba表达式中修改其值,外层变量可以不是final类型的,但是绝对不可以在lambda表达式中修改外层变量的值。(Variable used in lambda expression should be final or effectively final)

Optional.ofNullable(groupByFunction(list)).ifPresent(System.out::println);

Collector的方式

    private static Map<String, List<Apple>> groupByCollector(List<Apple> apples) {
        return apples.parallelStream().collect(groupingBy(Apple::getColor));
    }
Optional.ofNullable(groupByCollector(list)).ifPresent(System.out::println);

很快捷

Collector使用方法

公共类
Dish

public class Dish {

    private final String name;
    private final boolean vegetarian;
    private final int calories;
    private final Type type;

    public Dish(String name, boolean vegetarian, int calories, Type type) {
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
    }


    public String getName() {
        return name;
    }

    public boolean isVegetarian() {
        return vegetarian;
    }

    public int getCalories() {
        return calories;
    }

    public Type getType() {
        return type;
    }

    public enum Type {MEAT, FISH, OTHER}


    @Override
    public String toString() {
        return "Dish{" +
                "name='" + name + '\'' +
                ", vegetarian=" + vegetarian +
                ", calories=" + calories +
                ", type=" + type +
                '}';
    }
}

初始化数据

 public  static List<Dish> menu = Arrays.asList(
            new Dish("pork", false, 800, Dish.Type.MEAT),
            new Dish("beef", false, 700, Dish.Type.MEAT),
            new Dish("chicken", false, 400, Dish.Type.MEAT),
            new Dish("french fries", true, 530, Dish.Type.OTHER),
            new Dish("rice", true, 350, Dish.Type.OTHER),
            new Dish("season fruit", true, 120, Dish.Type.OTHER),
            new Dish("pizza", true, 550, Dish.Type.OTHER),
            new Dish("prawns", false, 300, Dish.Type.FISH),
            new Dish("salmon", false, 450, Dish.Type.FISH));

求卡路里的平均值

Collectors.averagingDouble/ Int/ Long

 private static void testAveragingDouble() {
        System.out.println("testAveragingDouble");
        //求 平均数 返回 double
        Optional.ofNullable(menu.stream().collect(Collectors.averagingDouble(Dish::getCalories)))
                .ifPresent(System.out::println);
    }

    private static void testAveragingInt() {
        System.out.println("testAveragingInt");
        Optional.ofNullable(menu.stream().collect(Collectors.averagingInt(Dish::getCalories)))
                .ifPresent(System.out::println);
    }

    private static void testAveragingLong() {
        System.out.println("testAveragingLong");
        Optional.ofNullable(menu.stream().collect(Collectors.averagingLong(Dish::getCalories)))
                .ifPresent(System.out::println);
    }

test

  public static void main(String[] args) {
        testAveragingDouble();
        testAveragingInt();
        testAveragingLong();
        }

在这里插入图片描述
java.util.stream.Collectors#averagingDouble 源码

    public static <T> Collector<T, ?, Double>
    averagingDouble(ToDoubleFunction<? super T> mapper) {  //ToDoubleFunction返回double类型
        /*
         * In the arrays allocated for the collect operation, index 0
         * holds the high-order bits of the running sum, index 1 holds
         * the low-order bits of the sum computed via compensated
         * summation, and index 2 holds the number of values seen.
         */
        return new CollectorImpl<>(
                () -> new double[4],
                (a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);},
                (a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
                a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
                CH_NOID);
    }

java.util.function.ToDoubleFunction
给任意一个参数返回一个double类型数据

@FunctionalInterface
public interface ToDoubleFunction<T> {

    /**
     * Applies this function to the given argument.
     *
     * @param value the function argument
     * @return the function result
     */
    double applyAsDouble(T value);
}

Collectors.collectingAndThen 修饰平均值结果 及 禁止修改

 private static void testCollectingAndThen() {
        System.out.println("testCollectingAndThen");

        String collect = menu.stream().collect(Collectors.collectingAndThen(
                Collectors.averagingInt(Dish::getCalories), a -> "The Average Calories is->" + a));

        Optional.ofNullable(collect).ifPresent(System.out::println);
    }

返回的东西会被修改怎么办

Collections::unmodifiableList
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));

实际上就是 将返回的结果 用 Collections.unmodifiableList(list);这个方法包装后再返回

List dishes = Collections.unmodifiableList(list);

    private static void testCollectingAndThen() {
        System.out.println("testCollectingAndThen");

        String collect = menu.stream().collect(Collectors.collectingAndThen(
                Collectors.averagingInt(Dish::getCalories), a -> "The Average Calories is->" + a));

        Optional.ofNullable(collect).ifPresent(System.out::println);


        List<Dish> list = menu.stream().filter(d -> d.getType().equals(Dish.Type.MEAT))
                .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));

        list.add(new Dish("", false, 100, Dish.Type.OTHER));

        System.out.println(list);
    }

在这里插入图片描述

统计返回结果数 Collectors.counting()

  private static void testCounting() {
        System.out.println("testCounting");
        Optional.of(menu.stream().collect(
                Collectors.counting()
        )).ifPresent(System.out::println);//9
    }

分组

按类型分组 Collectors.groupingBy(Dish::getType))

  private static void testGroupingByFunction() {
        System.out.println("testGroupingByFunction");
        Map<Dish.Type, List<Dish>> collect = menu.stream().collect(
                Collectors.groupingBy(Dish::getType)
        );
        Optional.of(collect).ifPresent(System.out::println);
    }

分类计算总数

    private static void testGroupingByFunctionAndCollector() {
        System.out.println("testGroupingByFunctionAndCollector");

        Map<Dish.Type, Long> collect = menu.stream().collect(
                Collectors.groupingBy(
                        Dish::getType,
                        Collectors.counting()
                ));
        Optional.of(collect).ifPresent(System.out::println);
    }

在这里插入图片描述

分类求卡路里平均值

  private static void testGroupingByFunctionAndCollector() {
        System.out.println("testGroupingByFunctionAndCollector");

        Map<Dish.Type, Double> collect = menu.stream().collect(
                Collectors.groupingBy(
                        Dish::getType, 
                        Collectors.averagingInt(Dish::getCalories)
                ));
        Optional.of(collect).ifPresent(System.out::println);
    }

在这里插入图片描述

分类求卡路里平均值 treeMap


    private static void testGroupingByFunctionAndSupplierAndCollector() {
        System.out.println("testGroupingByFunctionAndSupplierAndCollector");
        Map<Dish.Type, Double> map = menu.stream().collect(
                Collectors.groupingBy(Dish::getType, 
                                      TreeMap::new, 
                                      Collectors.averagingInt(Dish::getCalories)
                ));

        Optional.of(map.getClass()).ifPresent(System.out::println);
        Optional.of(map).ifPresent(System.out::println);
    }

Collectors.summarizingInt 求多个常规聚合值

   private static void testSummarizingInt() {
        System.out.println("testSummarizingInt");
        IntSummaryStatistics result = menu.stream().collect(
                Collectors.summarizingInt(Dish::getCalories)
        );
        Optional.of(result).ifPresent(System.out::println);
    }

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值