头歌-第1关:MapReduce的编程开发-求平均值

任务描述

本关任务:根据公司薪资数据,编写 MapReduce 程序来统计出各部门每月的平均薪资。

相关知识

求平均值概述

平均值有算术平均值,几何平均值,平方平均值(均方根平均值,rms),调和平均值,加权平均值等。其中以算术平均值最为常见。

算术平均数,又称均值,是统计学中最基本、最常用的一种平均指标,分为简单算术平均数、加权算术平均数。它主要适用于数值型数据,不适用于品质数据。根据表现形式的不同,算术平均数有不同的计算形式和计算公式。

求平均数是 MapReduce 比较常见的简单算法,使用 Map 端读取数据传入至 Reduce 端,在从 Reduce 端汇总并且统计总值与数量,将两值作商即可得出平均数。

数据文件格式说明

这是编程中用到的薪资数据,为 txt 格式,文件名salary.txt,大小12014行,前几行示例如下:

 
  1. 15298,销售部,Jan,6839.86
  2. 15298,销售部,Feb,9260.52
  3. 15298,销售部,Mar,5949.52
  4. 15298,销售部,Apr,9550.6
  5. 15298,销售部,May,8794.5
  6. 15298,销售部,Jun,7478.66
  7. 15298,销售部,Jul,7769.63
  8. 15298,销售部,Aug,6894.78
  9. 15298,销售部,Sep,6162.17
  10. 15298,销售部,Oct,7174.46
  11. 15298,销售部,Nov,9002.04
  12. 15298,销售部,Dec,7727.72
  13. 15232,财务部,Jan,6877.86
  14. 15232,财务部,Feb,6263.29
  15. 15232,财务部,Mar,6049.25
  16. 15232,财务部,Apr,5709.68
  17. 15232,财务部,May,7214.07
  18. 15232,财务部,Jun,7650.65
  19. 15232,财务部,Jul,6262.37
  20. 15232,财务部,Aug,6950.33
  21. 15232,财务部,Sep,5633.34
  22. 15232,财务部,Oct,5505.5
  23. 15232,财务部,Nov,6364.02
  24. 15232,财务部,Dec,5484.48
  25. ···
  26. --总共 12014行---
  • 每一行数据(4列)分别表示: 员工id, 部门名称, 月份, 薪资
  • 部门名称有 财务部、后勤部、销售部、人事部和研发部,总共5大类别;
  • 月份数据分别对应含义为:
月份含义
Jan1月
Feb2月
Mar3月
Apr4月
May5月
Jun6月
Jul7月
Aug8月
Sep9月
Oct10月
Nov11月
Dec12月

编程要求

根据提示,在右侧编辑器补充代码,计算得出各部门每月的平均薪资。

  • main 方法已给出,其中 Job 和输入输出路径已配置完成,无需更改;
  • map 和 reduce 的输入输出 key、value 已给出;
  • 编程中直接写 map 与 reduce 过程的主要内容即可。

预期输出格式:

 
  1. 部门名称 月份 薪资
  2. 部门名称 月份 薪资
  3. ···
  4. ···

测试说明

平台会对你编写的代码进行测试,如果编写的 MapReduce 输出与预期一致,则通过。


开始你的任务吧,祝你成功!

package avgsalary.mapreduce;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.LongWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.Job;

import org.apache.hadoop.mapreduce.Mapper;

import org.apache.hadoop.mapreduce.Reducer;

import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class AvgSalaryDriver {

    public static class Map extends Mapper<LongWritable, Text,Text,Text>{

        @Override

        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {

            /********** Begin **********/

            //获取输入的行

            String line=value.toString();

            String[] tokens=line.split(",");

            //取出无效记录

            if(tokens.length!=4){

                return;

            }

            //以 , 分割成字符串列表

            String department=tokens[1];

            String month=tokens[2];

            double salary=Double.parseDouble(tokens[3]);

            //将结果写出去

            context.write(new Text(department+"\t"+month),new Text(String.valueOf(salary)));

            /********** End **********/

        }

    }

    public static class  Reduce extends Reducer<Text, Text,Text,Text>{

        @Override

        protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {

            /********** Begin **********/

            //定义总薪资

            double totalSalary=0;

            int count=0;

            //定义数量

           

            //遍历集合求总薪资

            for(Text value:values){

                totalSalary+=Double.parseDouble(value.toString());

                count++;

            }

            //求平均薪资

            double avgSalary=totalSalary/count;

            String formattedAverage=String.format("%.2f",avgSalary);

            //把结果写出去

            String[] tokens=key.toString().split("\t");

            String department=tokens[0];

            String month=tokens[1];

            context.write(new Text(department),new Text(month+"\t"+formattedAverage));

            /********** End **********/

        }

    }

    public static void main(String[] args) throws  Exception {

        //创建配置信息

        Configuration conf=new Configuration();

        // 创建任务

        Job job = Job.getInstance(conf);

        //设置执行类

        job.setJarByClass(AvgSalaryDriver.class);

        //设置自定义Mapper类

        job.setMapperClass(Map.class);

        //设置自定义Reducer类

        job.setReducerClass(Reduce.class);

        //设置map函数输出数据的key和value的类型

        job.setMapOutputKeyClass(Text.class);

        job.setMapOutputValueClass(Text.class);

        //设置reduce函数输出数据的key和value的类型

        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(Text.class);

        //如果输出目录存在,我们就删除

        String outputpath="/root/files";

        Path path=new Path(outputpath);

        FileSystem fileSystem=path.getFileSystem(conf);

        if (fileSystem.exists(path)){

            fileSystem.delete(path,true);

        }

        //设置输入输出路径

        FileInputFormat.addInputPath(job,new Path("/data/workspace/myshixun/data/salary.txt"));

        FileOutputFormat.setOutputPath(job,path);

        //提交作业,若成功返回true,失败返回falase

        boolean b=job.waitForCompletion(true);

        if (b){

            System.out.println("恭喜,清洗成功");

        }else{

            System.out.println("不好意思,清洗失败");

        }

    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值