Spark学习之路(九):使用分组取TopN算法配合Spark算子实现复杂业务逻辑案例实战

一、分组取TopN算法

  • 所谓“分组取TopN”其实就是在给定的一堆杂乱无章的数据中根据一个或多个分组的依据对数据先进行分组,然后在分好组的每一组数据内,再根据一个维度或者多个维度对组内的数据进行排序,然后找出每个小组的组内TopN的元素,这就是分组取TopN。
  • 分组取TopN在数据处理过程中非常之常见,也非常的有意义,比如电商平台想找出本季度最受欢迎的Top5商品种类,且要找出Top5商品种类中每个种类的TopN受欢迎的商品,这就用到了分组取TopN算法,下面会基于一个需求来使用这个算法并配合Spark算子来完成比较复杂的业务逻辑。

二、需求分析及实现逻辑

  • 有如下需求:有一批学生成绩数据,字段与字段之间用制表符隔开,字段分别是学生编号、班级编号、语文成绩、数学成绩、英语成绩,现在要求按班级学生总分的平均分先找出班级平均分前三的班级```,然后在每个前三班级中再找出班里成绩总分最高的三人。
  • 数据样式为:
    36886	class2	88	39	66
    88323	class3	91	38	43
    94680	class4	72	31	34
    41687	class3	31	78	90
    84712	class3	34	38	52
    
  • 实现逻辑:
    1.从本地文件读取数据,生成studentRDD;
    2.由学生信息的各科成绩算出该学生的总分,并追加写入在学生信息里;
    3.将每条学生成绩数据先按班级id作为Key,学生信息作为Value映射为一个元组,生成class2StudentRDD;
    4.按班级id进行分组,得到每个班级所有学生的信息,生成class2AllStudentRDD;
    5.算出每个班级的平均分,将班级平均分作为Key,班级id作为Value映射为元组,生成avgScore2ClassidRDD;
    6.按照平均分降序排序并取出平均分前三的班级,生成to3ClassList;
    7.将平均分前三的班级集合序列化为top3ClassRDD然后将top3ClassRDD的Key与 Value互换与classid2AllStudent进行job操作,可以得到Top3班级每个班级所有学生的信息生成top3Class2StudentRDD;
    8.分组取TopN算法实现每个班级取成绩前三的学生,生成classid2Top3StudentRDD;
    9.将classid2Top3StudentRDD的数据写入外部文件系统;
  • 以上RDD的血缘关系图为:
    在这里插入图片描述

三、需求分步骤实现详细代码讲解

1.从数据源读取数据创建RDD
// 该路径一般为HDFS路径,现在本地演示,所以为本地路径
 JavaRDD<String> studentRDD = sc.textFile("C:\\Users\\XJH\\Desktop\\student.txt");
2.处理原始数据,创建元组RDD
// 1.由学生信息的各科成绩算出该学生的总分,并追加写入在学生信息里
 // 2.将每条学生成绩数据先按班级id作为Key,学生信息作为Value映射为一个元组
 JavaPairRDD<String,String> classid2Student = studentRDD.mapToPair(
     new PairFunction<String, String, String>() {
   
         public Tuple2<String, String> call(String student) {
   
             String[] studentMessage = student.split("\t");
             // 取出班级id
             String classID = studentMessage[1];
             // 取出语文成绩
             Integer chinese = Integer.valueOf(studentMessage[2]);
             // 取出数学成绩
             Integer manth = Integer.valueOf(studentMessage[3]);
             // 取出英语成绩
             Integer english = Integer.valueOf(studentMessage[4]);
             // 算出总分并将总分信息追加至学生信息末尾
             Integer totalScore = chinese + manth + english;
             student += "\t" + String.valueOf(totalScore);
             // 返回一个元组
             return new Tuple2<String, String>(classID,student);
     }
 });
3.将数据以班级id分组
JavaPairRDD<String,Iterable<String>>  classid2AllStudent =  classid2Student.groupByKey();
4.计算每个班级的平均分,并将平均分作为Key,班级ID作为Value创建RDD
 // 算出每个班级的平均分,将班级平均分作为Key,班级id作为Value映射为元组
JavaPairRDD<Integer,String> classid2AVGScore = classid2AllStudent.mapToPair(
    new PairFunction<Tuple2<String, Iterable<String>>, Integer, String>() {
   
        public Tuple2<Integer, String> call(Tuple2<String, Iterable<String>> tuple) {
   
            // 取出班级id
            String classID = tuple._1;
            // 班级人数
            int numStudents = 0;
            // 班级总分
            int totalScore = 0;
           Iterator<String> iterator = tuple._2.iterator();
           while (iterator.hasNext()){
   
               // 该字段是根据学生各科成绩算出来追加到学生信息后面的
               totalScore += Integer.valueOf(iterator.next().split("\t")[5]);
               numStudents ++
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值