MR案例一(wordcount)
前面的文章写了HDFS和Mapreduce的机制,现在我们要动手写一些最基本的分布式计算实例。
本章主要写最基本的wordcount的一个基础demo,后面会逐渐进行丰富和完善。有基础的大佬还望勿喷。
目的
我们要完成一个MR,进行分词和计数
由:
最终得到:
目录结构
具体代码
mapper
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
/*
* 继承Mapper类,源码我们后面再看
* 其中的四个参数分别是Mapper的输入(2)和输出(2)
* LongWritable和IntWritable 相当于int, Text相当于String
* 第一个参数是游标,可以简单的理解为行号,而第一个Text是String
* 那么第一步就得到了{
* (第一行)1 XXXXX
* .....
* }
* 而最后两个参数是代表每个词和它的个数。
* 这是分完词的以一个阶段的输出。
* 至于为什么不是使用java的int和String类型其实是一中序列化,也就是hadoop框架中的自己的序列化方式,这种方式比使用java中的更有优势。
*/
Text k = new Text();
IntWritable v = new IntWritable();
//这个key和value是输入到context中的,而context的方法是Map和reduce两个阶段的数据通路,他是连接的关键。
@Override
protected void map(LongWritable key,
Text value,
Context context) throws IOException, InterruptedException {
//第一步 转化格式
String line0 = value.toString();
//第二部 切分数据 按空格切分数据
String[] words = line0.split(" ");
//第三步 输出<单词 , 1>
for (String word : words) {
k.set(word);
v.set(1);
context.write(k,v);
}
}
}
reduce:
当我们得到了mapper中的<word,1>这种key value格式的context后,就会进入到reduce处理阶段。
package MRcode;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
public class WordCountReducer extends Reducer<Text, IntWritable,Text,IntWritable> {
@Override
protected void reduce(Text key,
Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
//上面的Iterable是迭代器,用于计算有相同的key的value值的总和。
//初始化次数
int count=0;
//汇总次数
for(IntWritable value : values){
count += value.get();
}
//输出总次数
context.write(key,new IntWritable(count));
}
}
driver:
package MRcode;
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 java.io.IOException;
public class WorkCountDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
args = new String[] {"InputPathString","OutPutPathString"};
//获取配置信息
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
job.setJarByClass(WorkCountDriver.class);
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//反射类设置mapper,reducer,driver类
//map输出类型 也就是reducer的输入
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//reduce 输出的K,V类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.setInputPaths(job,new Path(args[0]));
FileOutputFormat.setOutputPath(job,new Path(args[1]));
//提交job
job.waitForCompletion(true);
}
}
最终我们得到上述中的结果。
这就完成一了一个简单的MR程序。
其中比较需要注意的是Mapper,Reducer的主要过程,和他们的输入输出类型。
比较高结合复杂的mapreduce程序我将在后面的blog中介绍。