Hadoop的第一行代码WordCount
一、程序功能描述:
给定一个文本文件(words.txt),例如:
Hello World
Hello Tom
Hello Helen
Hello Baby
Hello HeiLi
Hello Bob
Hello Lisa
Hello Jerry
对其中所涉及到的单词进行统计,并输出。输出格式为:
Hello 8
World 1
Tom 1
Helen 1
Baby 1
HeiLi 1
Bob 1
Lisa 1
Jerry 1
DG
二、程序结构,及功能:
本程序涉及到三个类,分别是:WCMapper.java;WCReducer.java;WCRunner.java
其中WCMapper功能为(以给定文本的第一行为例子):
1、对于给定的输入文本进行一行一行的读取。并进行单词切割得到数组:[ Hello,World]
2、遍历单词数组,输出<Hello,1>,<World,1>到WCReducer类中。
当读完整个文本文件时候,输出的结果类似于键值对:
<Hello,1,1,1,1,1,1,1,1>
<World,1>
<Tom,1>
<Helen,1>
<Baby,1>
<HeiLi,1>
<Bob,1>
<Lisa,1>
<Jerry,1>
对于WCReducer类来说:
根据WCMapper类的输入作为输入,将每一个输入值进行逻辑处理,对于
<Hello,1,1,1,1,1,1,1,1>来说,将后面的1进行累计,累加后的值即为Hello在文本中出现的次数。即得到结果为<Hello,8>。
同理可知WCReducer类处理后的结果为键值对:
<Hello,8>
<World,1>
<Tom,1>
<Helen,1>
<Baby,1>
<HeiLi,1>
<Bob,1>
<Lisa,1>
<Jerry,1>
对于WCReducer类来说:
起作用在穿件一个Job类并利用Job类绑定Map和Reduce,并且设定一些参数用来指定Job的一些属性,例如输入文本位置,输出结果存放位置……。
三、代码实例
1、WCMapper.java
package com.haifeng.hadoop.mapreduce.wordcount;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
/*
*编写WCMapper作为Map 需要集成Mapper 类,泛型类中参数:1、LongWritable 输入文本中,读取*行的起始偏移量位置(我们可以理解为该类型类似与java的Long类),2、Text 是改行的的字符串内*容(我们可以理解给该类型类似于java中的String类),3、Text为该类输出后的内容(即上述例子中*<Hello,8>中的Hello)4、LongWritable为该类输出后的内容(即上述例子中<Hello,8>中的8)
*/
public class WCMapper extends Mapper<LongWritable, Text, Text, LongWritable> {
//需要重写map方法,Mapper类每读文本一行就会调用一次该方法。
protected void map(LongWritable key, Text value, Context context)
throws java.io.IOException, InterruptedException {
//获取一行的文本内容,并转成字符串类型
String line = value.toString();
//对获取的一行文本进行切割
String[] words = StringUtils.split(line, " ");
for (String word : words) {
/*
* 通过context来写入处理后的内容,第一个参数是切割后的一个个单词,第二个参数
* 就是单词的计数值
*/
context.write(new Text(word), new LongWritable(1));
}
};
}
WCReducer.java
package com.haifeng.hadoop.mapreduce.wordcount;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
//作为一个Reduce,集成Reducer类并重写其中的reduce方法,其中的泛型参数与Mapper泛型参数性质类似
public class WCReducer extends Reducer<Text, LongWritable, Text, LongWritable> {
/*
*重写reduce方法,框架在Map处理完成之后,将所有的KV键值对缓存起来进行分组,然后传递
*一个组<key,values{}>,调用一次reduce方法
*/
protected void reduce(Text key, Iterable<LongWritable> values,
Context context) throws java.io.IOException, InterruptedException {
long count = 0;
for (LongWritable value : values) {
/*
*对传来的类似与键值对后棉的values{},进行累计,累加结果为该字符串在文本中
*出现的次数
*/
count += value.get();
}
//计算后的结果作为输出写到context对象中
context.write(key, new LongWritable(count));
};
}
WCRunner.java
/**
*用来描述一个热定的作业
*比如,改作业使用那个类作为处理中的Map,那个类作为处理中的Reduce
*还可以指定改作业要处理的数据所在的位置,以及指定作业输出存放的路径
*/
package com.haifeng.hadoop.mapreduce.wordcount;
import java.io.IOException;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class WCRunner {
/**
* @param args
* @throws IOException
* @throws InterruptedException
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//该实例初始创建是包含初始化一个作业所属要的一部分属性值
Configuration conf = new Configuration();
//新建一个作业,参数为conf
Job job = Job.getInstance(conf);
/*
*设置整个job所用的那些类在那个jar包,由于这三个类都在容一个包下,故可用本来作为参
*数
*/
job.setJarByClass(WCRunner.class);
//指定该Job中的Map和Reducer
job.setMapperClass(WCMapper.class);
job.setReducerClass(WCReducer.class);
//指定Reducer的输出类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class);
//指定Map的输出类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(LongWritable.class);
//指定输入输出类型
FileInputFormat.setInputPaths(job, new Path("/wc/srcdata/"));
FileOutputFormat.setOutputPath(job, new Path("/wc/output/"));
//将job提交给集群运行,true为打印运行是产生的信息,false为不打印信息
job.waitForCompletion(true);
}
}