WordCount官方代碼的詳解
作爲小白的我初次在hadoop裏接觸mapReduce程序,難免會有些費解以及難懂代碼所蘊含的意思,經過自己查閱資料以及消化,便得到下面代碼的的解釋:
package homework;
import java.io.IOException;
import java.util.StringTokenizer;
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.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
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 {
/*
* 假設需要統計的內容爲:
* hello wordcount good
* good wordcount nice
*
* 在進行map方法統計之前系統會進行預處理,分割成<key,value>
* <0,hello wordcount good>
* <20,good wordcount nice>
* 注:每行都分割一堆鍵值對的形式,有多少行就執行多少次mapper方法進行分割
*
* Mapper的前兩個參數Object、Text是輸入參數類型<Object,Text>,後兩個參數Text、IntWritable是輸出參數類型<Text,IntWritable>
*/
//map部分
public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{
//創建一個不賦值、且爲靜態變量one,數值爲1,意思是分割後每個單詞都記錄爲1個
private final static IntWritable one = new IntWritable(1);
//創建一個Test類型的變量word,用於記錄後面把分割後的字符
private Text word = new Text();
//key是輸入參數的鍵,value是輸入參數的值,context是設置map的輸出值
public void map(Object key, Text value, Context context ) throws IOException, InterruptedException {
//StringTokenizer是一個用來分隔String的應用類,在這裏是先把value的Text類型轉爲String類型再創建一個StringTokenizer類的分割對象itr
StringTokenizer itr = new StringTokenizer(value.toString()); //默認以空格,回車\r,換行\n,製表符\t和換頁符\f
//while循環,判斷條件是hasMoreTokens,返回表示是否還有分隔符的boolean類型
while (itr.hasMoreTokens()) {
//itr.nextToken():返回當前位置到下一個分隔符的字符串,這裏整體就是把分割出來的字符串再次轉換爲Text類型的word對象
word.set(itr.nextToken());
//設置進行mapper方法後的輸出值
context.write(word, one);
}
}
}
/*
* 到reduce部分
* 到這裏的內容應爲:
* <hello,1>
* <wordcount,1>
* <good,1>
* <good,1>
* <wordcount,1>
* <nice,1>
*
* Reduce部分同樣有四個參數,前兩個是輸入參數類型,如:<hello,1>,後面兩個是輸出參數類型
*/
public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> {
//reducer是負責數據合併的,那麼會將具有相同key的內容合併一起
//這裏的第二個參數實際上類似於一個數組,數組元素類型爲IntWritable
//實際輸入的內容轉換爲:
/*
* <hello,[1]>
* <wordcount,[1,1]>
* <good,[1,1]>
* <nice,[1]>
*
* 這裏有多少個鍵值對,reduce方法就執行多少次進行數量統計
*/
//創建一個私有的空的IntWritable對象,用於後面做單數統計個數
private IntWritable result = new IntWritable();
//這裏的參數與上面的map方法類似,但是第二個參數是一個類似於IntWritable類型的values數組,context用於設置輸出值
public void reduce(Text key, Iterable<IntWritable> values, Context context ) throws IOException, InterruptedException {
//初始化單詞統計數量
int sum = 0;
//遍歷數組裏的元素進行相加,便得到單詞出現的次數
for (IntWritable val : values) {
//用IntWritable類型的val變量遍歷出values數組的元素需要轉換成int類型再進行相加,用IntWritable類的get方法的該對象的int類型
sum += val.get();
}
//得到單詞出現的次數sum再而用IntWritable的result對象把它設置爲IntWritable類型
result.set(sum);
//最後輸出reduce的結果,如<wordcount,2>
context.write(key, result);
}
}
//主函數部分
public static void main(String[] args) throws Exception {
/*
*Configuration這個類是作業的配置信息類,任何作用的配置信息必須通過Configuration傳遞,
* 因爲通過Configuration可以實現在多個mapper和多個reducer任務之間共享信息
*/
Configuration conf = new Configuration();
//配置程序函數的輸入參數,將輸入參數放置到字符串數組otherArgs中
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
//如果程序的輸入不是兩個就會退出並打印"Usage: wordcount <in> <out>"提示信息
if (otherArgs.length != 2) {
System.err.println("Usage: wordcount <in> <out>");
System.exit(2);
}
//設置mapreduce任務的代號,“word count”代號可以隨意取
Job job = new Job(conf, "word count");
//設置jar包程序運行時的主類名稱,與類名吻合
job.setJarByClass(WordCount.class);
//設置程序負責mapper功能的類名,與上TokenizerMapper符合
job.setMapperClass(TokenizerMapper.class);
//job.setCombinerClass(IntSumReducer.class);
//設置程序負責reducer功能的類名,與IntSumReducer上符合
job.setReducerClass(IntSumReducer.class);
//設置reduce函數的輸出鍵類型
job.setOutputKeyClass(Text.class);
//設置reduce函數的輸出值類型
job.setOutputValueClass(IntWritable.class);
//程序輸入參數的第一個爲輸入內容
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
//程序輸入參數的第二個爲輸出內容
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
//等待執行完畢,執行完就退出
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
Mapreduce源碼官方解讀文檔
有不足之處,希望留言指正!