Java8 Stream(10)Collectors groupingBy partitioningBy 案例详解

  • Post author:
  • Post category:java

Java8 Stream最为优秀且便捷的当属它的收集器,Collectors实现了很多有用的方法。

学习并熟练运用Collectors能大大提高开发效率。

先早点数据

pigs.add(new Pig(1, "猪爸爸", 31, "M", false));
pigs.add(new Pig(2, "猪妈妈", 28, "F", true));
pigs.add(new Pig(3, "乔治", 2, "M", false));
pigs.add(new Pig(4, "佩奇", 5, "F", false));
pigs.add(new Pig(5, null, 1, "F", false));

一、获得对象中某1个属性集合

1. toList 获取id的List集合

List<Integer> idList = pigs.stream()
        .map(Pig::getId)
        .collect(Collectors.toList());

2. toSet 获取gender的Set集合

Set<String> genderSet = pigs.stream()
		.map(Pig::getGender)
		.collect(Collectors.toSet());

二、List 转 Map

1. toMap 将List的值转成 id -> name的Map

Map<Integer, String> idNameMap = pigs.stream()
        .collect(
                Collectors.toMap(
                        Pig::getId,
                        Pig::getName
                )
        );

因为id=5的name是null,所以报错NullPointerException。

通过下面判断name是否为null,来解决该问题

Map<Integer, String> idNameMap = pigs.stream()
        .collect(
                Collectors.toMap(
                        Pig::getId,
                        pig -> pig.getName() == null ? "" : pig.getName()
                )
        );

2. 解决key重复后异常

如果key重复,会报异常,这个时候得指定重复用哪一个,得加上(oldValue, newValue) -> newValue)

        Map<String, String> genderNameMap = pigs.stream()
                .collect(
                        Collectors.toMap(
                                Pig::getGender,
                                pig -> pig.getName() == null ? "" : pig.getName(),
                                (oldValue, newValue) -> newValue)
                );

三、求和 最大值 最小值 平均值

1. 求age最大的对象

Optional<Pig> maxAgePig = pigs.stream()
        .filter(a -> a.getAge() != null)
        .collect(
                Collectors.maxBy(
                        Comparator.comparing(Pig::getAge)
                )
        );

2. 求age的平均值

Double avgAge = pigs.stream()
        .filter(a -> a.getAge() != null)
        .collect(
                Collectors.averagingInt(Pig::getAge)
        );

3. 求age总和

Integer sumAge = pigs.stream()
        .collect(
                Collectors.summingInt(Pig::getAge)
        );

4. 求统计信息

IntSummaryStatistics statisticsAge = pigs.stream()
        .collect(
                Collectors.summarizingInt(Pig::getAge)
        );
System.out.println("sumAge = " + statisticsAge);

结果如下:

sumAge = IntSummaryStatistics{count=5, sum=67, min=1, average=13.400000, max=31}

四、joining 拼接字符串

String ids = pigs.stream()
        .map(a -> String.valueOf(a.getId()))
        .collect(Collectors.joining(","));
System.out.println("ids = " + ids);

结果如下:

ids = 1,2,3,4,5

五、groupingBy 分组

1. 一级分组

根据Gender分组

//一级分组
Map<String, List<Pig>> groupByGender = pigs.stream()
        .collect(
                Collectors.groupingBy(Pig::getGender)
        );

结果如下:

F -> [Pig(id=2, name=猪妈妈, age=28, gender=F, valid=true), Pig(id=4, name=佩奇, age=5, gender=F, valid=false), Pig(id=5, name=null, age=1, gender=F, valid=false)]
M -> [Pig(id=1, name=猪爸爸, age=31, gender=M, valid=false), Pig(id=3, name=乔治, age=2, gender=M, valid=false)]

2. 一级分组,且统计count

统计每个性别的个数

Map<String, Long> groupByGenderThenCount = pigs.stream()
        .collect(
                Collectors.groupingBy(
                        Pig::getGender,
                        Collectors.counting()
                )
        );

结果如下:

F -> 3
M -> 2

3. collectingAndThen 分组后再比较

按照性别分组后,再求各自中年级最小的

Map<String, Pig> groupByGenderThenMinAge = pigs.stream()
        .collect(
                Collectors.groupingBy(
                        Pig::getGender,
                        Collectors.collectingAndThen(
                                Collectors.minBy(
                                        Comparator.comparingInt(Pig::getAge)
                                ),
                                Optional::get
                        )
                )
        );

4. 二级分组

先gender分组,后valid分组

Map<String, Map<Boolean, List<Pig>>> groupByGenderAndValid = pigs.stream()
        .collect(
                Collectors.groupingBy(
                        Pig::getGender,
                        Collectors.groupingBy(Pig::isValid)
                )
        );

结果如下:

F -> {false=[Pig(id=4, name=佩奇, age=5, gender=F, valid=false), Pig(id=5, name=null, age=1, gender=F, valid=false)], true=[Pig(id=2, name=猪妈妈, age=28, gender=F, valid=true)]}
M -> {false=[Pig(id=1, name=猪爸爸, age=31, gender=M, valid=false), Pig(id=3, name=乔治, age=2, gender=M, valid=false)]}

六、partitioningBy 分区

1. 按照是否age>20来分区

Map<Boolean, List<Pig>> partByAge = pigs.stream()
        .collect(
                Collectors.partitioningBy(a -> a.getAge() > 20)
        );

结果如下:

false -> [Pig(id=3, name=乔治, age=2, gender=M, valid=false), Pig(id=4, name=佩奇, age=5, gender=F, valid=false), Pig(id=5, name=null, age=1, gender=F, valid=false)]
true -> [Pig(id=1, name=猪爸爸, age=31, gender=M, valid=false), Pig(id=2, name=猪妈妈, age=28, gender=F, valid=true)]

2. 按照是否age>20来分区,再统计count

Map<Boolean, Long> partByAgeThenCount = pigs.stream()
        .collect(
                Collectors.partitioningBy(
                        a -> a.getAge() > 20,
                        Collectors.counting()
                )
        );

结果如下:

false -> 3
true -> 2

版权声明:本文为winterking3原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。