Java8新特性-Stream API 之Collector(三)

本文介绍 Java 中 Stream API 的 Collectors 工厂类提供的多种汇聚操作方法,并通过实例演示了如何使用这些方法来实现常见数据处理任务,包括筛选最大元素、元素分组、计算总和、平均值等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Collector与Collectors之间的关系

作为collect方法的参数,Collector是一个接口,它是一个可变的汇聚操作,将输入元素累计到一个可变的结果容器中;它会在所有元素都处理完毕后,将累积的结果转换为一个最终的表示(这是一个可选操作);

Collectors本身提供了关于Collector的常见汇聚实现,Collectors的内部类CollectorImpl实现了Collector接口,Collectors本身实际上是一个工厂。

Collectors提供哪些方法

工厂方法名返回类型作用
toListList<T>List集合
toSetSet<T>Set<T>,去重
maxByOption<T>Optional<T>
groupingByMap<key,List>元素分组
summingIntInteger所有元素某个属性求和
averagingIntInteger所有元素某个属性的平均值
summarizingIntIntSummaryStatistics一次获取多个值, count, sum, min, max, average
joiningString将所有的元素的某个属性拼接成字符串
reducing累加的类型累加计算
collectingAndThen转换函数返回的类型包裹另一个收集器,对其结果应用转换函数
partitioningByMap<Boolean,List<T>>根据对流中每个项目应用谓词的结果来对项目进行分区
collectingAndThen转换函数返回的类型包裹另一个收集器,对其结果应用转换函数
public class CollectorsDemo {

    public static void main(String[] args) {


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


        //maxby  test  筛选出最大的元素
        Comparator<Dish> dishCaloriesComparator =
                comparingInt(Dish::getCalories);
        menu.stream().collect(maxBy(dishCaloriesComparator))
                .ifPresent(a -> System.out.println("max calories --->" + a.getCalories()));

        //groupingby test  将元素的某个属性提取出来进行分组
        Map<Dish.Type, List<Dish>> map = menu.stream().collect(groupingBy(Dish::getType));
        for (Map.Entry<Dish.Type, List<Dish>> entry : map.entrySet()) {
            System.out.println(entry.getKey() + "---" + entry.getValue().size());
        }

        //summingInt test  计算所有元素的和
        int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));

        //averagingInt test  计算所有元素的平均值
        double averageCalories = menu.stream().collect(averagingInt(Dish::getCalories));

        //summarizingInt test  一次获取多个值, count, sum, min, max, average
        IntSummaryStatistics menuStatistics =
                menu.stream().collect(summarizingInt(Dish::getCalories));
        System.out.println(menuStatistics.toString());


        //join  test  joining(",") 可以指定连接符,避免拼接字符串,还要对最后一个元素进行特殊处理
        // 如:每个元素拼接 element+"," 最后去掉最后一个","号
        String shortMenu = menu.stream().map(Dish::getName).collect(joining(","));
        System.out.println("join test --->" + shortMenu);


        //reducing 实现
        menu.stream().collect(Collectors.reducing(
                0,               //初始值
                Dish::getCalories,      //转换函数
                (a, b) -> a + b));           //累计函数
        menu.stream().collect(Collectors.reducing(0, Dish::getCalories, Integer::sum));



        //获取热量最高的值,默认值有可能为空所以返回Optional,
        menu.stream().collect(Collectors.reducing(
                (d1, d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2))
                .ifPresent(a -> System.out.println("max calories---" + a.getCalories()));


        // 根据需要修改key,修改lambda表达式里面的逻辑
        Map<CaloricLevel, List<Dish>> dishesByCaloricLevel = menu.stream().collect(
                groupingBy(dish -> {
                    return getLevel(dish);
                }));

        //二级分组
        Map<Dish.Type, Map<CaloricLevel, List<Dish>>> dishesByTypeCaloricLevel =
                menu.stream().collect(
                        groupingBy(Dish::getType,
                                groupingBy(dish -> {
                                    return getLevel(dish);
                                })
                        )
                );


        //获取每种类型中热量最高的dish
        Map<Dish.Type, Optional<Dish>> mostCaloricByType =
                menu.stream()
                        .collect(groupingBy(Dish::getType,
                                maxBy(comparingInt(Dish::getCalories))));

        //将optional直接转换要用collectingAndThen
        Map<Dish.Type, Dish> mostCaloricDish =
                menu.stream()
                        .collect(groupingBy(Dish::getType,
                                Collectors.collectingAndThen(
                                        maxBy(comparingInt(Dish::getCalories)),
                                        Optional::get)));


        //格式化value的方法
        Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType =
                menu.stream().collect(
                        groupingBy(Dish::getType, Collectors.mapping(
                                dish -> {
                                   return getLevel(dish);
                                },
                                Collectors.toSet())));
        //分区partitioningBy test,传入谓词
        Map<Boolean, List<Dish>> partitionedMenu =
                menu.stream().collect(Collectors.partitioningBy(Dish::isVegetarian));

        //只返回符合条件的
        List<Dish> vegetarianDishes =
                menu.stream().filter(Dish::isVegetarian).collect(Collectors.toList());
        System.out.println(vegetarianDishes.size());

    }

    public enum CaloricLevel {DIET, NORMAL, FAT}


    public static CaloricLevel getLevel(Dish dish){
        if (dish.getCalories() <= 400) return CaloricLevel.DIET;
        else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
        else return CaloricLevel.FAT;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值