百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

Java菜谱(二)——怎么计算一个班级男学生的平均分?

yuyutoo 2024-10-24 17:50 10 浏览 0 评论

今天的场景设计是这样的:

给定一批学生分数的数据,求出所有男学生的平均分数。

如果这个命题放在sql中,应该是送分题。在Java中去实现,可能也没有那么难。但是当场景不断复杂化,我们就需要一些技巧来解决这类问题了。现在我们就来探讨一下如何通过Stream流式编程解决这一类问题。

假设Student类的数据结构如下:

@Data
public class Student {
    /**
     * 学生ID
     */
    private String id;
    /**
     * 学生姓名
     */
    private String name;
    /**
     * 学生年龄
     */
    private Integer age;
    /**
     * 学生性别 0-女 1-男
     */
    private Integer gender;
    /**
     * 学生成绩
     */
    private Double score;
}

传统思路

假设学生的数据是以List<Student>的形式给出的,让我们先来回顾一下传统思路是怎么解决这个问题的,由于

平均分数=总分/人数

因此,我们需要两个临时变量,一个用于记录总分,另一个用于记录男学生的人数。然后对学生列表进行遍历,如果遍历到男学生,则总分加上当前学生的分数,人数加1,示例代码如下:

Double totalScore = 0.0; // 总分
int count = 0; // 数量
for (Student student : students) {
    // 男学生
    if (student.getGender() == 1) {
        totalScore += student.getScore();
        count++;
    }
}
// 按公式求取平均分
Double average = totalScore / count;

这样的思路属于命令式编程的范式,即我们一步一步告诉计算机先做什么再做什么,其好处是逻辑简单,容易理解和编写,也容易调试。但是这样的方式编程通常代码量巨大,并且很容易编写出执行效率低下的代码,处理复杂逻辑时更是容易丢掉代码的可读性。

Stream流式计算

在Jdk8以后,Java引入了lambda表达式和Stream。Lambda表达式使得Java可以更方便地使用函数式的风格编写程序,Stream的引入更是极大简化了集合的操作。

那么就让我们来看一下在Stream的帮助下如何解决上面的问题:

Double average = students.stream()
            .filter(s -> s.getGender() == 1)
            .collect(Collectors.averagingDouble(Student::getScore));

上述代码看上去很简短,但实际包含了三个步骤:

  1. 首先通过列表的stream()方法将列表转为流,
  2. 再通过filter方法对流中的元素进行过滤,
  3. 最后通过collect方法对流中的元素进行归并,得到最终的结果。

事实上,所有使用流的场景都遵循这三个步骤,即流的创建、流的转换以及流的归并。

上述流式计算的方式是一种函数式编程的风格,同时也是属于声明式编程的范式。相比于命令式编程,声明式编程更强调告诉计算机要做什么,而不是具体怎么做。每个步骤具体的实现方案由计算机内部自行实现。当然,这也依赖于Jdk内部提供的强大的api。

更复杂的场景

让我们把场景变得更复杂一些,来见识一下流式计算的威力。

复杂场景1:学生属于不同班级,需要计算每个班男同学的平均分

学生的类增加班级字段,改造为:

@Builder
@Data
public class Student {
    /**
     * 学生ID
     */
    private String id;
    /**
     * 学生姓名
     */
    private String name;
    /**
     * 学生年龄
     */
    private Integer age;
    /**
     * 学生性别 0-女 1-男
     */
    private Integer gender;
    /**
     * 学生成绩
     */
    private Double score;
    /**
     * 学生属于哪个班
     */
    private Integer classNumber;
}

上述需求实现代码如下:

Map<Integer, Double> averageMap = students.stream()
          .filter(s -> s.getGender() == 1)
          .collect(Collectors.groupingBy(Student::getClassNumber, 
                   Collectors.averagingDouble(Student::getScore)));

由于需要每个班的成绩,我们对学生按班级进行分组,使用的是Collectors工具类提供的groupingBy()方法。这个方法第一个参数是分类的依据,这里传的是Student::getClassNumber这个方法引用,即怎么根据学生对象获取到学生的班级。第二个参数传的是下游的收集器,即分组之后对每组元素做怎样的操作,这里和之前一样传的是对学生的成绩取平均分的操作。如果我们只对数据进行分组,不进行后续处理,第二个参数可以不传(重载方法)。

复杂场景2:计算分数高于平均分的学生人数

// 先求平均分
Double average = students.stream()
    .collect(Collectors.averagingDouble(Student::getScore));

// 再求超过平均分的人数
long count = students.stream()
    .filter(s -> s.getScore() > average)
    .count();

这个需求想整合成一次流式操作比较困难,因此我们可以先获取班级的平均分,再去计算分数超过平均分的人数。

需要注意的是,Stream对象是“一次性的”,当一次归并操作完成后,Stream就会被关闭,这时如果复用之前的对象就会抛出异常。

这里只举这两个例子,Stream还有很多方便的API,感兴趣的可以自行尝试。总结一下,使用Stream可以极大简化集合相关的操作,如果有相关的数据处理需求,可以尝试使用。

欢迎各位留言讨论,如果您觉得有帮助,还请多多点赞、转发支持~

相关推荐

Python操作Word文档神器:python-docx库从入门到精通

Python操作Word文档神器:python-docx库从入门到精通动动小手,点击关注...

Python 函数调用从入门到精通:超详细定义解析与实战指南 附案例

一、函数基础:定义与调用的核心逻辑定义:函数是将重复或相关的代码块封装成可复用的单元,通过函数名和参数实现特定功能。它是Python模块化编程的基础,能提高代码复用性和可读性。定义语法:...

等这么长时间Python背记手册终于来了,入门到精通(视频400集)

本文毫无套路!真诚分享!前言:无论是学习任何一门语言,基础知识一定要扎实,基础功非常的重要,找一个有丰富编程经验的老师或者师兄带着你会少走很多弯路,你的进步速度也会快很多,无论我们学习的目的是什么,...

图解Python编程:从入门到精通系列教程(附全套速查表)

引言本系列教程展开讲解Python编程语言,Python是一门开源免费、通用型的脚本编程语言,它上手简单,功能强大,它也是互联网最热门的编程语言之一。Python生态丰富,库(模块)极其丰富,这使...

Python入门教程(非常详细)从零基础入门到精通,看完这一篇就够

本书是Python经典实例解析,采用基于实例的方法编写,每个实例都会解决具体的问题和难题。主要内容有:数字、字符串和元组,语句与语法,函数定义,列表、集、字典,用户输入和输出等内置数据结构,类和对象,...

Python函数全解析:从入门到精通,一文搞定!

1.为什么要用函数?函数的作用:封装代码,提高复用性,减少重复,提高可读性。...

Python中的单例模式:从入门到精通

Python中的单例模式:从入门到精通引言单例模式是一种常用的软件设计模式,它保证了一个类只有一个实例,并提供一个全局访问点。这种模式通常用于那些需要频繁创建和销毁的对象,比如日志对象、线程池、缓存等...

【Python王者归来】手把手教你,Python从入门到精通!

用800个程序实例、5万行代码手把手教你,Python从入门到精通!...

Python从零基础入门到精通:一个月就够了

如果想从零基础到入门,能够全职学习(自学),那么一个月足够了。...

Python 从入门到精通:一个月就够了

要知道,一个月是一段很长的时间。如果每天坚持用6-7小时来做一件事,你会有意想不到的收获。作为初学者,第一个月的月目标应该是这样的:熟悉基本概念(变量,条件,列表,循环,函数)练习超过30个编...

Python零基础到精通,这8个入门技巧让你少走弯路,7天速通编程!

Python学习就像玩积木,从最基础的块开始,一步步搭建出复杂的作品。我记得刚开始学Python时也是一头雾水,走了不少弯路。现在回头看,其实掌握几个核心概念,就能快速入门这门编程语言。来聊聊怎么用最...

神仙级python入门教程(非常详细),从0到精通,从看这篇开始!

python入门虽然简单,很多新手依然卡在基础安装阶段,大部分教程对一些基础内容都是一带而过,好多新手朋友,对一些基础知识常常一知半解,需要在网上查询很久。...

Python类从入门到精通,一篇就够!

一、Python类是什么?大家在生活中应该都见过汽车吧,每一辆真实存在、能在路上跑的汽车,都可以看作是一个“对象”。那这些汽车是怎么生产出来的呢?其实,在生产之前,汽车公司都会先设计一个详细的蓝图...

学习Python从入门到精通:30天足够了,这才是python基础的天花板

当年2w买的全套python教程用不着了,现在送给有缘人,不要钱,一个月教你从入门到精通1、本套视频共487集,本套视频共分4季...

30天Python 入门到精通(3天学会python)

以下是一个为期30天的Python入门到精通学习课程,专为零基础新手设计。课程从基础语法开始,逐步深入到面向对象编程、数据处理,最后实现运行简单的大语言模型(如基于HuggingFace...

取消回复欢迎 发表评论: