java8Collector

文章目录

  • 初识Collector体会Collector的强大
    • 聚合
    • 分组
      • 传统做法
      • lamda 函数式编程
      • Collector的方式
  • Collector使用方法
    • 求卡路里的平均值
      • Collectors.averagingDouble/ Int/ Long
      • Collectors.collectingAndThen 修饰平均值结果 及 禁止修改
    • 统计返回结果数 Collectors.counting()
    • 分组
      • 按类型分组 Collectors.groupingBy(Dish::getType))
      • 分类计算总数
      • 分类求卡路里平均值
      • 分类求卡路里平均值 treeMap
      • Collectors.summarizingInt 求多个常规聚合值

初识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 list = Arrays.asList(
                new Apple("green", 150),
                new Apple("yellow", 120),
                new Apple("green", 170));

        List 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> groupByNomal(List apples){
        Map> map = new HashMap<>();
        for (Apple apple : apples) {
            List 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> groupByFunction(List apples) {
        Map> map = new HashMap<>();
        apples.parallelStream().forEach(a -> {
            List colorList = Optional.ofNullable(map.get(a.getColor())).orElseGet(() -> {
                List 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> groupByCollector(List 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 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();
        }

java8Collector_第1张图片
java.util.stream.Collectors#averagingDouble 源码

    public static  Collector
    averagingDouble(ToDoubleFunction 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 {

    /**
     * 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 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);
    }

java8Collector_第2张图片

统计返回结果数 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> collect = menu.stream().collect(
                Collectors.groupingBy(Dish::getType)
        );
        Optional.of(collect).ifPresent(System.out::println);
    }

分类计算总数

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

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

java8Collector_第3张图片

分类求卡路里平均值

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

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

java8Collector_第4张图片

分类求卡路里平均值 treeMap


    private static void testGroupingByFunctionAndSupplierAndCollector() {
        System.out.println("testGroupingByFunctionAndSupplierAndCollector");
        Map 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);
    }

java8Collector_第5张图片

你可能感兴趣的:(jdk8)