成绩统计
任务描述
本关任务:使用Map/Reduce
计算班级中年龄最大的学生。
相关知识
为了完成本关任务,你需要掌握:1.什么是MapReduce
,2.如何使用MapReduce
进行运算。
什么是MapReduce
MapReduce
是一种可用于数据处理的编程模型,我们现在设想一个场景,你接到一个任务,任务是:挖掘分析我国气象中心近年来的数据日志,该数据日志大小有3T
,让你分析计算出每一年的最高气温,如果你现在只有一台计算机,如何处理呢?我想你应该会读取这些数据,并且将读取到的数据与目前的最大气温值进行比较。比较完所有的数据之后就可以得出最高气温了。不过以我们的经验都知道要处理这么多数据肯定是非常耗时的。
如果我现在给你三台机器,你会如何处理呢?看到下图你应该想到了:最好的处理方式是将这些数据切分成三块,然后分别计算处理这些数据(Map
),处理完毕之后发送到一台机器上进行合并(merge
),再计算合并之后的数据,归纳(reduce
)并输出。
这就是一个比较完整的MapReduce
的过程了。
如何使用MapReduce进行运算
我们通过一个示例,来体验Map/Reduce
的使用。
我们从一个问题入手:目前我们想统计两个文本文件中,每个单词出现的次数。
首先我们在当前目录下创建两个文件:
创建file01
输入内容:
Hello World Bye World
创建file02
输入内容:
Hello Hadoop Goodbye Hadoop
将文件上传到HDFS
的/usr/input/
目录下:
不要忘了启动DFS
: start-dfs.sh
然后创建文件夹并上传:
在右侧代码区域编写,文件WordCount.java
,添加如下内容:
public class WordCount {
//Mapper类
/*因为文件默认带有行数,LongWritable是用来接受文件中的行数,
第一个Text是用来接受文件中的内容,
第二个Text是用来输出给Reduce类的key,
IntWritable是用来输出给Reduce类的value*/
public static class TokenizerMapper
extends Mapper<LongWritable, Text, Text, IntWritable>{
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(LongWritable key, Text value, Context context
) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
}
public static class IntSumReducer
extends Reducer<Text,IntWritable,Text,IntWritable> {
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values,
Context context
) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
public static void main(String[] args) throws Exception {
//创建配置对象
Configuration conf = new Configuration();
//创建job对象
Job job = new Job(conf, "word count");
//设置运行job的类
job.setJarByClass(WordCount.class);
//设置Mapper的类
job.setMapperClass(TokenizerMapper.class);
//设置Reduce的类
job.setReducerClass(IntSumReducer.class);
//设置输出的key value格式
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//设置输入路径
String inputfile = "/usr/input";
//设置输出路径
String outputFile = "/usr/output";
//执行输入
FileInputFormat.addInputPath(job, new Path(inputfile));
//执行输出
FileOutputFormat.setOutputPath(job, new Path(outputFile));
//是否运行成功,true输出0,false输出1
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
点击评测,运行代码,可以看到/usr/output
目录下已经生成了文件。
我们来查看part--r-00000
文件的内容: