输入:hello hadoop
hello word
下面是map函数
import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Mapper; public class MapperClass extends Mapper<Object,Text, Text, IntWritable>{//四个参数的含义,前两个输入,后两个输出 ,类型需一致 public Text keytext =new Text("text");//定义一个text对象,用来充当中间变量,存储词 public IntWritable intvalue=new IntWritable(1);//词的个数,刚开始都为1,也可以不定义,直接context.write(keytext, 1); @Override protected void map(Object key, Text value, Context context)//key即行偏移量,作用不大,主要是value,根据value进行拆分 throws IOException, InterruptedException { //获取值 String str =value.toString(); //分隔 StringTokenizer stringTokenizer=new StringTokenizer(str);//StringTokenizer根据空格等分隔字符串到stringTokenizer while (stringTokenizer.hasMoreElements()) {//返回是否还有分隔符,判断是否还有单词 keytext.set(stringTokenizer.nextToken());//nextToken():返回从当前位置到下一个分隔符的字符串。 context.write(keytext, intvalue);//context.write("hello",1) } } }
reduce函数
import java.io.IOException; import java.util.Iterator; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; public class ReducerClass extends Reducer<Text, IntWritable, Text, IntWritable> {// 前两个输入:例:(hello,1),后两个输出(hello,2) public IntWritable intValue = new IntWritable(0); @Override protected void reduce(Text key, Iterable<IntWritable> values,// 这里声明了一个实现Iterator接口的匿名内部类,并返回了内部类的实例 Context context)// 它用来与MapReduce系统进行通信,如把map的结果传给reduce处理 throws IOException, InterruptedException { // step1 int sum = 0; Iterator<IntWritable> itr = values.iterator();// 迭代器,访问容器中的元素,为容器而生 while (itr.hasNext()) { sum += itr.next().get();// 如果有,则加入迭代器中的个数 } intValue.set(sum);// 对于hello,sum是2 context.write(key, intValue);// hello,2 } }
主函数:
import org.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; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import org.apache.hadoop.util.GenericOptionsParser; public class WordCount { public static void main(String[] args) throws Exception{ Configuration conf =new Configuration();//指定作业执行规范 String[] otherArgs =new GenericOptionsParser(conf,args).getRemainingArgs(); if(otherArgs.length !=2) { System.err.println("Usage:wordcount <in> <out>"); System.exit(2); } Job job =new Job(conf,"word count");//指定job名称,及运行对象 job.setJarByClass(WordCount.class); job.setMapperClass(MapperClass.class);//指定map函数 job.setCombinerClass(ReducerClass.class);//是否需要conbiner整合 job.setReducerClass(ReducerClass.class);//指定reduce函数 job.setOutputKeyClass(Text.class);//输出key格式 job.setOutputValueClass(IntWritable.class);//输出value格式 FileInputFormat.addInputPath(job, new Path(otherArgs[0]));//处理文件路径 FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));//结果输出路径 System.exit(job.waitForCompletion(true)?0:1); } }
小结:Hadoop程序处理流程
(1)将文件拆分为splits,并由MapReduce框架自动完成分割,将每一个split分割为<key,value>对
(2)每一对<key,value>调用一次map函数,处理后生产新的<key,value>对,由Context传递给reduce处理
(3)Mapper对<key,value>对进行按key值进行排序,并执行Combine过程,将key值相同的value进行合并。最后得到Mapper的最终输出结果
(4)reduce处理,处理后将新的<key,value>对输出。