WordCount单词统计分析
最近在网上看了hadoop相关资料以及单词计数的一个实例,结合网上的资料和自己的看法简要分析一下执行过程。
MyMapper.java
package com.mpred;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class MyMapper extends Mapper<LongWritable, Text, Text,IntWritable> {
@Override
protected voidmap(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String val=value.toString();
String str[]=val.split(" ");
for(String s:str){
context.write(new Text(s),new IntWritable(1));
}
}
}
MyReducer.java
package com.mpred;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
importorg.apache.hadoop.mapreduce.Reducer;
public class MyReducer extends Reducer<Text, IntWritable, Text,IntWritable> {
/* (non-Javadoc)
* @seeorg.apache.hadoop.mapreduce.Reducer#reduce(java.lang.Object,java.lang.Iterable, org.apache.hadoop.mapreduce.Reducer.Context)
*/
@Override
protected voidreduce(Text key, Iterable<IntWritable> values,
Context context)
throws IOException, InterruptedException {
int sum=0;
for(IntWritable val:values){
sum+=val.get();
}
context.write(key,new IntWritable(sum));
}
}
WordCount.java
package com.mpred;
import java.io.IOException;
importorg.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
importorg.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class WordCount {
public staticvoidmain(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
Configuration conf=new Configuration();//加载配置文件
Job job=new Job(conf);//创建一个job,供JobTracker使用
job.setJarByClass(WordCount.class);
job.setMapperClass(MyMapper.class);
job.setReducerClass(MyReducer.class);
FileInputFormat.addInputPath(job,newPath("hdfs://192.168.0.9:9000/hello.txt"));
FileOutputFormat.setOutputPath(job,new Path("hdfs://192.168.0.9:9000/wordcount"));
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
System.exit(job.waitForCompletion(true)?0:1);
}
}
输入文件
hello you
hello me
follow me
followyou
执行流程简要分析:
1. map任务处理
a) 读取文件内容,解析成key、value对。对输入文件的每一行,解析成key、value对。每一个键值对调用一个map函数。
b) 在map函数中可以编写自己的逻辑,对输入的key、value处理,转换成新的key、value输出。
c) 对输出的key、value进行分区。
d) 对不同分区的数据,按照key进行排序、分组。相同key的value放到一个集合中。
2. reduce任务处理
a) 对多个map任务的输出,按照不同的分区,通过网络copy到不同的reduce节点。
b) 对多个map任务的输出进行合并、排序。写reduce函数自己的逻辑,对输入的key、reduce处理,转换成新的key、value输出。
c) 把reduce的输出保存到文件中。
分析以上示例代码:
输入文件的分析:
helloyou //key是0,value是hello you
hello me //key是10,value是hello me
注:map函数的key表示字节偏移量,value表示一行文本内容。
map函数分析:
protected void map(LongWritable key, Text value, Contextcontext)
throws IOException, InterruptedException {
String val=value.toString();
String str[]=val.split(" ");
for(String s:str){
context.write(new Text(s),new IntWritable(1));
}
}
key为偏移量,value为每一行的数据;通过split方法(按空格)分离出每一个单词;然后通过循环输出每一组单词(<hello,1>,<you,1>,<hello,1>,<me,1>)
排序后的结果:<hello,1>,<hello,1>,<me,1>,<you,1>
分组后的结果:<hello,{1,1}>,<me,{1}>,<you,{1}>
reduce函数分析
protected void reduce(Text key, Iterable<IntWritable>values,
Context context)
throws IOException, InterruptedException {
int sum=0;
for(IntWritable val:values){
sum+=val.get();
}
context.write(key,new IntWritable(sum));
}
key为单词,value为单词数的集合;可以看出reduce函数将会被调用3次,每一次调用都会计算values集合的和,然后输出每一组数据
reduce输出后的数据为<hello,2>,<you,1>,<me,1>
至此map和reduce函数执行完毕,将数据写入文件。