Java 8 lambda maxBy取最大/minBy取最小取平均值counting计数partitioningBy分隔/groupingBy分组

Java 8 辣么大(lambda)表达式不慌之—–(五)示例-Collectors中的统计、分组、排序等
summarizingInt 按int类型统计
maxBy取最大/minBy取最小
averagingInt /averagingLong/averagingDouble取平均值
counting计数
partitioningBy分隔/groupingBy分组
sorted 排序

还是先定义好后面做示例要用的数据:
List<User> listUser = new ArrayList<>();
listUser.add(new User("李白", 20, true));
listUser.add(new User("杜甫", 40, true));
listUser.add(new User("李清照", 18, false));
listUser.add(new User("李商隐", 23, true));
listUser.add(new User("杜牧", 39, true));
listUser.add(new User("苏小妹", 16, false));
1
2
3
4
5
6
7
这个User就是一个普通的Bean对象,有name(姓名)、age(年龄)、gender(性别)三个属性及对应的set/get方法。

summarizingInt 按int类型统计
IntSummaryStatistics summaryStatistics = listUser.stream().collect(Collectors.summarizingInt(User::getAge));
System.out.println("年龄平均值:" + summaryStatistics.getAverage()); // 年龄平均值:26.0
System.out.println("人数:" + summaryStatistics.getCount()); // 人数:6
System.out.println("年龄最大值:" + summaryStatistics.getMax()); // 年龄最大值:40
System.out.println("年龄最小值:" + summaryStatistics.getMin()); // 年龄最小值:16
System.out.println("年龄总和:" + summaryStatistics.getSum()); // 年龄总和:156
1
2
3
4
5
6
一个方法把统计相关的基本上都搞定了,美滋滋。这里是按int统计,同样他也有 summarizingLong、summarizingDouble方法,跟这个类似。
嫌这个方法多余的话,也有单个的统计方法。

maxBy取最大/minBy取最小
方法定义如下:

    public static <T> Collector<T, ?, Optional<T>>
    maxBy(Comparator<? super T> comparator) {
        return reducing(BinaryOperator.maxBy(comparator));
    }
1
2
3
4
参数传的是一个Comparator,举例说明:

        // 根据指定条件取最大值: 取年纪最大的人
        Optional<User> optional = listUser.stream().collect(Collectors.maxBy(Comparator.comparing((user) -> {
            return user.getAge();
        })));
        if (optional.isPresent()) { // 判断是否有值
            User user = optional.get();
            System.out.println("最大年纪的人是:" + user.getName()); // 输出==》 最大年纪的人是:杜甫
        }
1
2
3
4
5
6
7
8
取最小的与取最大的是一样的道理:

        // 根据指定条件取最小值: 取年纪最小的人
        Optional<User> optional = listUser.stream().collect(Collectors.minBy(Comparator.comparing((user) -> {
            return user.getAge();
        })));
        if (optional.isPresent()) { // 判断是否有值
            User user = optional.get();
            System.out.println("最小年纪的人是:" + user.getName()); // 输出==》 最小年纪的人是:苏小妹
        }
1
2
3
4
5
6
7
8
averagingInt /averagingLong/averagingDouble取平均值
方法定义:

    public static <T> Collector<T, ?, Double>
    averagingInt(ToIntFunction<? super T> mapper) {
        return new CollectorImpl<>(
                () -> new long[2],
                (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; },
                (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
                a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);
    }
1
2
3
4
5
6
7
8
传一个ToIntFunction类型的参数,这里说一下ToIntFunction。前面说过Function<T, R>的定义,T是入参的类型R是返回值的类型,与Function<T, R>相应的有IntFunction,他规定死入参类型是int,返回类型自定义;然后一个ToIntFunction他的入参类型是自定义,返回类型定死了是int。同理其他的Long类型的,Double类型的一样。
所以我们此处的averagingInt这样写:

ToIntFunction<User> mapper = (user)->{
    return user.getAge();
};
Double averageAge = listUser.stream().collect(Collectors.averagingInt(mapper ));
System.out.println("平均年齡是:" + averageAge); // 输出--》 平均年齡是:26.0
1
2
3
4
5
或者

Double averageAge = listUser.stream().collect(Collectors.averagingInt(User::getAge));
System.out.println("平均年齡是:" + averageAge); // 输出--》 平均年齡是:26.0
1
2
counting计数
counting方法很简单,直接上例子:

int count = listUser.stream().collect(Collectors.counting());  // count其实就等于listUser.size();
1
此处单纯数个数没什么用,相当于listUser.size(); 。但是可以结合其他方法使用,如结合filter使用求男性数量:

Long count = listUser.stream().filter(user -> user.getGender()).collect(Collectors.counting()); 
System.out.println("男性个数:" + count); // 输出--》 男性个数:2
1
2
partitioningBy分隔/groupingBy分组
partitioningBy 方法的定义:

groupingBy方法的定义:

通过定义可以看到,partitioningBy的第一个参数是一个Predicate,而groupingBy的第一个参数是一个Function<T,R>,Predicate返回的是Boolean类型而Function<T,R>返回的是自己定义的类型。所以当分组的依据是Boolean类型的时候这两个方法使用效果一样,如:

// 将List中的人按性别分组
Predicate<User> predicate = (user) -> {
    return user.getGender();
};
Map<Boolean, List<User>> partition = listUser.stream().collect(Collectors.partitioningBy(predicate));

Function<User, Boolean> classifier = (user) -> {
    return user.getGender();
};
Map<Boolean, List<User>> groupby = listUser.stream().collect(Collectors.groupingBy(classifier));
1
2
3
4
5
6
7
8
9
10
上面2个方法得到的结果是一样的,因为从上面的2个函数predicate和classifier的定义可以看到,2个函数的实现是一样的。但是如果想要按其他类型的数据(如String)来进行分组的话 partitioningBy就要略逊一筹了,如按User的姓名来分组,partitioningBy就不好写了,groupingBy可以稍微改一下就行:

Function<User, String> classifier = (user) -> {
    return user.getName();
};
Map<String, List<User>> groupby = listUser.stream().collect(Collectors.groupingBy(classifier));
1
2
3
4
sorted 排序
这个方法不是Collectors的方法,是Stream接口里面的一个方法。作用就是将Stream里面的元素排序,但是有个前提是里面的内容是Comparable的(或者说实现过Comparable接口的),否则会抛出异常。
如上的listUser,如果直接写:

List<User> sorted = listUser.stream().sorted().collect(Collectors.toList());
1
就会抛出Exception in thread "main" java.lang.ClassCastException: User cannot be cast to java.lang.Comparable异常。
所以要先让User对象实现一下Comparable接口并重写compareTo方法:

    @Override
    public int compareTo(User user) {
        return this.getAge().compareTo(user.getAge());
    }
1
2
3
4
这样上面的sorted()方法就能按年龄来排序了。
或者User对象不实现一下Comparable接口,就直接写:

List<User> sorted3 = listUser.stream()
        .sorted((x, y) -> (x.getAge() < y.getAge()) ? -1 : ((x.getAge() > y.getAge()) ? 1 : 0))
        .collect(Collectors.toList());
1
2
3
道理是一样的,写法不一样罢了。
————————————————
版权声明:本文为CSDN博主「DWT_CCFK」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012843361/article/details/83094827

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万事俱备,就差一个程序员了

谢谢您,赏俺根辣条,尝尝鲜.谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值