具体代码如下:
<span style="font-family: Arial, Helvetica, sans-serif;">import java.io.IOException;</span>
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.mapreduce.lib.partition.HashPartitioner;
public class WordCountApp {
static final String INPUT_PATH="hdfs://chaoren:9000/hello";//这里hello是一个文件,当然也可以文件夹
static final String OUTPUT_PATH="hdfs://chaoren:9000/out";
static class Mymapper extends Mapper<LongWritable, Text, Text, LongWritable>{
@Override
protected void map(LongWritable key, Text value, Context c1)
throws IOException, InterruptedException {
String[] splited=value.toString().split(" ");
for (String word : splited) {
c1.write(new Text(word), new LongWritable(1));
}
}
}
static class Myreducer extends Reducer<Text, LongWritable, Text, LongWritable>{
@Override
protected void reduce(Text text, Iterable<LongWritable> values,Context c2)
throws IOException, InterruptedException {
Long times=0L;
for (LongWritable count : values) {
times +=count.get();//使用get()方法将hadoop中count变量的LongWritable数据类型转换为java中类型,然后与times相加
}
c2.write(text, new LongWritable(times));
}
}
public static void main(String[] args) throws Exception {
Configuration conf=new Configuration();
Job job=new Job(conf, WordCountApp.class.getSimpleName());
//指定读取的文件的位置
FileInputFormat.setInputPaths(job, INPUT_PATH);
//指定如何对输入文件进行格式化,把输入文件的每一行解析成键值对
job.setInputFormatClass(TextInputFormat.class);
//指定自定义的map类
job.setMapperClass(Mymapper.class);
//指定map输出的<k,v>类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(LongWritable.class);
//分区
job.setPartitionerClass(HashPartitioner.class);
//因为有一个reduce,所以值设置一个reduce任务运行
job.setNumReduceTasks(1);
//排序、分组
//归约
//指定自定义的reduce类
job.setReducerClass(Myreducer.class);
//指定reduce的输出类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class);
//指定写出到哪里
FileOutputFormat.setOutputPath(job, new Path(OUTPUT_PATH));
//指定输出文件的格式化类
job.setOutputFormatClass(TextOutputFormat.class);
//把job提交给JobTracker运行
job.waitForCompletion(true);
}
}
具体实现过程入下:(为了说清楚,本过程是按照待处理文件个数为两个的情况说明的)
引自http://www.cnblogs.com/xia520pi/archive/2012/05/16/2504205.html
1)将文件拆分成splits,由于测试用的文件较小,所以每个文件为一个split,并将文件按行分割形成<key,value>对,如图1-1所示。这一步由MapReduce框架自动完成,其中偏移量(即key值)包括了回车所占的字符数(Windows和Linux环境会不同)。
图1-1 分割过程
2)将分割好的<key,value>对交给用户定义的map方法进行处理,生成新的<key,value>对,如图1-2所示。
图1-2 执行map方法
3)得到map方法输出的<key,value>对后,Mapper会将它们按照key值进行排序,并执行Combine过程,将key值相同value值累加,得到Mapper的最终输出结果。如图1-3所示。
图1-3 Map端排序及Combine过程
4)Reducer先对从Mapper接收的数据进行排序,再交由用户自定义的reduce方法进行处理,得到新的<key,value>对,并作为WordCountApp的输出结果,如图1-4所示。
图1-4 Reduce端排序及输出结果