WordCount实例是大数据学习过程中的入门,相当于学习各种编程语言时打印“Hello World”的一样。本次实验是通过Java代码来实现的。
- 数据准备
任意创建一个文本文件,在其中写入一些单词,并用空格隔开。 - Mapper阶段:
mapper阶段结束后,数据将会被拆分成一个个<单词, 1>的键值对形式。经过shuffle过程后,形成<单词, <1, 1, 1, 1, ……>>形式,而后传递给reducer处理。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; /** * WordCount程序 Mapper类 * * 自定义的xxxMapper类,需要继承Hadoop提供的Mapper类,并重写map方法 * * 按照当前WordCount程序来分析: * 四个泛型: 两组kv对 * 输入数据的kv类型: * KEYIN : LongWritable 表示文件读取数据的偏移量,简单理解为每次从文件的哪个位置开始读取数据. * VALUEIN : Text 实际从文件中读取的一行数据 * 输出数据的kv类型: * KEYOUT : Text, 表示一个单词 * VALUEOUT : IntWritable, 表示这个单词出现了1次. */ public class WordCountMapper extends Mapper<LongWritable, Text,Text, IntWritable> { // 定义输出的k(单词) 和 v(单词数,1) private Text outk = new Text(); private IntWritable outv = new IntWritable(1); /** * Map阶段处理的业务逻辑 * @param key KEYIN 输入数据的key * @param value VALUEIN 输入数据的value * @param context 上下文对象,负责整个Mapper类指定过程的调度. */ @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { //1. 获取到输入的一行数据 String line = value.toString(); //2. 切割 String[] words = line.split(" "); //3. 将每个单词拼成kv写出 for (String word : words) { //封装k 和 v outk.set(word); //写出 context.write(outk,outv); } } }
- Reducer阶段
Reducer阶段主要是对shuffle阶段的value-list进行处理,类加求和,最终以<k, v>对的形式输出import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; /** * WordCount程序的 Reducer类 * * 自定义的xxxReducer类需要继承Hadoop提供的Reducer类,重写reduce方法 * * 按照当前wordCount程序来分析: * 4个泛型 : 两组kv对 * 输入数据的kv类型: Reducer输入数据的kv对象要对应Mapper输出数据的kv类型 * KEYIN : Text 表示一个单词 * VALUEIN : IntWritable 表示该单词出现了1次 * 输出数据的kv类型: * KEYOUT : Text 表示一个单词 * VALUEOUT: IntWritable 表示该单词总共出现的次数 */ public class WordCountReducer extends Reducer<Text, IntWritable,Text,IntWritable> { //定义输出的v private IntWritable outv = new IntWritable(); /** * Reduce阶段的业务逻辑处理 * @param key KEYIN , 表示一个单词 * @param values 迭代器对象, 表示一个相同的单词(相同key)出现的次数的封装. 能够表明当前 的单词出现了多少次. * @param context 上下文对象, 负责Reducer类执行过程的调度 */ @Override protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { // 定义变量求和 int sum = 0; // 1. 将当前的单词出现的次数进行汇总. for (IntWritable value : values) { sum += value.get(); } // 2. 封装k和v outv.set(sum); // 3. 写出 context.write(key,outv); } }
- Driver阶段:
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; /** * WordCount程序的 Driver类 */ public class WordCountDriver { public static void main(String[] args) throws Exception { //1.获取Job对象 Configuration conf = new Configuration(); Job job = Job.getInstance(conf); //2.关联jar,设置驱动类 job.setJarByClass(WordCountDriver.class); //3.关联Mapper 和 Reducer job.setMapperClass(WordCountMapper.class); job.setReducerClass(WordCountReducer.class); //4.设置Mapper 输出的key 和 value的类型 job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(IntWritable.class); //5.设置最终输出的key 和 value的类型 // 如果有reducer,就写reducer输出的kv类型,如果没有reducer,就写mapper输出的kv类型. job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); //6.设置输入和输出路径 FileInputFormat.setInputPaths(job,new Path("文件所在路径")); FileOutputFormat.setOutputPath(job,new Path("结果输出路径")); // 输出目录不能存在,否则会报异常 //7.提交Job job.waitForCompletion(true); } }