學習Hadoop第一個MapReduce程序WordCount的詳解

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源碼官方解讀文檔
有不足之處,希望留言指正!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章