输入: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>对输出。