Java Stream 分组

117 阅读2分钟

1. 单级分组

//接收一个 Function 参数
groupingBy(Function<? super T, ? extends K> classifier)

栗子:

/**
 * Stream流数据--分组操作
 * 备注:切记Stream流只能被消费一次,流就失效了
 * 如下只是示例代码
 * @author liuzebiao
 */
public class CollectDataToArray{
 
    public static void main(String[] args) {
        Stream<Student> studentStream = Stream.of(
                new Student("赵丽颖", 52, 56),
                new Student("杨颖", 56, 88),
                new Student("迪丽热巴", 56, 99),
                new Student("柳岩", 52, 53)
        );
        
        //1.按照具体年龄分组
        Map<Integer, List<Student>> map = studentStream.collect(Collectors.groupingBy((s -> s.getAge())));
        map.forEach((key,value)->{
            System.out.println(key + "---->"+value);
        });
 
        //2.按照分数>=60 分为"及格"一组  <60 分为"不及格"一组
        Map<String, List<Student>> map = studentStream.collect(Collectors.groupingBy(s -> {
            if (s.getScore() >= 60) {
                return "及格";
            } else {
                return "不及格";
            }
        }));
        map.forEach((key,value)->{
            System.out.println(key + "---->"+value.get());
        });
 
        //3.按照年龄分组,规约求每组的最大值最小值(规约:reducing)
        Map<Integer, Optional<Student>> reducingMap = studentStream.collect(
                Collectors.groupingBy(Student::getAge, 
                        Collectors.reducing(
                                BinaryOperator.maxBy(
                                        Comparator.comparingInt(Student::getScore)
                                )
                        )
                )
        );
        reducingMap .forEach((key,value)->{
            System.out.println(key + "---->"+value);
        });
    }
}

结果:

52---->[Student{name='赵丽颖', age=52, score=56}, Student{name='柳岩', age=52, score=53}]
56---->[Student{name='杨颖', age=56, score=88}, Student{name='迪丽热巴', age=56, score=99}]
不及格---->[Student{name='赵丽颖', age=52, score=56}, Student{name='柳岩', age=52, score=53}]
及格---->[Student{name='杨颖', age=56, score=88}, Student{name='迪丽热巴', age=56, score=99}]
52---->Student{name='赵丽颖', age=52, score=95}
56---->Student{name='杨颖', age=56, score=88}

2. 多级分组

语法:

//接收两个参数: 1.Function 参数  2.Collector多级分组
groupingBy(Function<? super T, ? extends K> classifier,Collector<? super T, A, D> downstream)

举个栗子:

/**
 * Stream流数据--多级分组操作
 * 备注:切记Stream流只能被消费一次,流就失效了
 * 如下只是示例代码
 * @author liuzebiao
 * @Date 2020-1-10 13:37
 */
public class CollectDataToArray{
 
    public static void main(String[] args) {
        Stream<Student> studentStream = Stream.of(
                new Student("赵丽颖", 52, 95),
                new Student("杨颖", 56, 88),
                new Student("迪丽热巴", 56, 55),
                new Student("柳岩", 52, 33)
        );
 
        //多级分组
        //1.先根据年龄分组,然后再根据成绩分组
        //分析:第一个Collectors.groupingBy() 使用的是(年龄+成绩)两个维度分组,所以使用两个参数 groupingBy()方法
        //    第二个Collectors.groupingBy() 就是用成绩分组,使用一个参数 groupingBy() 方法
        Map<Integer, Map<Integer, Map<String, List<Student>>>> map = studentStream.collect(Collectors.groupingBy(str -> str.getAge(), Collectors.groupingBy(str -> str.getScore(), Collectors.groupingBy((student) -> {
            if (student.getScore() >= 60) {
                return "及格";
            } else {
                return "不及格";
            }
        }))));
 
        map.forEach((key,value)->{
            System.out.println("年龄:" + key);
            value.forEach((k2,v2)->{
                System.out.println("\t" + v2);
            });
        });
    }
}

结果:

年龄:52
{不及格=[Student{name='柳岩', age=52, score=33}]}
{及格=[Student{name='赵丽颖', age=52, score=95}]}
年龄:56
{不及格=[Student{name='迪丽热巴', age=56, score=55}]}
{及格=[Student{name='杨颖', age=56, score=88}]}