本例通过对输入文件中的学生的三科成绩进行计算,得出每个学生的平均成绩。输入文件中的每行内容均为一个学生的姓名和其相应的成绩,每门学科为一个文件。要求输出结果中每行有两个数据,其中第一个代表学生的姓名,第二个代表其平均成绩。
输入的三个文件内容如下:
math.txt:
张三 88 李四 99 王五 66 赵六 77
chinese.txt:
张三 78 李四 89 王五 96 赵六 67
english.txt:
张三 80 李四 82 王五 84 赵六 86
期望输出结果如下:
张三 82 李四 90 王五 82 赵六 76
根据MapReduce的工作原理可知,Map任务最终处理的结果对<key,value>会送到Reduce任务进行合并,具有相同key的<key,value>对会送到同一个Reduce任务中进行处理,即Reduce任务处理的数据是key和这个key对应的所有value的一个集合(value-list)。
MapReduce经典的单词计数例子是将接收到的每一个value-list进行求和,进而得到所需的结果。而本例中,我们将Reduce任务接收到的value-list进行求平均分后,作为输出的value值即可,输出的key值仍然为接收到的key。
整个求平均分的流程如图5-9所示。
图5-9 MapReduce求平均分的执行流程
项目的新建及依赖jar包的引入参见5.4节的数据去重案例,此处不再赘述。
本例完整的程序源代码如下:
需要注意的是,Hadoop在涉及编码时默认使用的是UTF-8,如果文件编码格式是其他类型(如GBK),则会出现乱码。此时只需在map()或reduce()方法中读取Text时,进行一下转码操作,确保都是以UTF-8的编码方式在运行即可,转码的核心代码如下:
String line=new String(value.getBytes(),0,value.getLength(),"UTF-8");
程序的打包和运行参考前面的“单词计数”和“数据去重”案例,此处不再赘述。
执行完成后,查看HDFS的/output目录生成的结果内容,如图5-10所示。
图5-10 查看HDFS结果内容