MapReduce實現WordCount以及常見問題解決

Hadoop環境開發環境測試

 最近在做一個大數據方面的小工程,需要使用基於hadoop環境進行計算。MapReduce是Hadoop生態系統下的成熟的計算框架,在開發之前需要搭建MapReduce開發環境並測試。
 由於我本身就是大數據方面的新手,因此在開始的時候遇到不小的麻煩,但在慢慢的尋找解決辦法的過程中還是有所感悟的,因此有必要做一下記錄,希望給讀者有所幫助!
通常我們需要在搭好的hadoop環境下進行“wordcount”程序測試,好看是否能夠正常運行。一開始一般是不能直接成功運行WordCount程序的,因爲在windows系統下,system32文件下缺少必要文件“winutils.exe”,另外在hadoop版本文件bin目
錄下缺少文件“hadoop.dll”文件。大家可以在點擊這裏下載。

 step1:向HDFS上傳一個包含一以下內容的txt文件number.txt

 對文件數據使用MapReduce編程:

package cn.edu.nuist.wordcount;

import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;

import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.FileInputFormat;
import org.apache.hadoop.mapred.FileOutputFormat;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.MapReduceBase;
import org.apache.hadoop.mapred.Mapper;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reducer;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.mapred.TextInputFormat;
import org.apache.hadoop.mapred.TextOutputFormat;
/**
 * 
 * 描述:WordCount explains 
 * @author Hadoop Dev Group
 */
public class WordCount
{
	private static String inPath = "/countWords/number.txt";
	private static String outPath = "/countWords/output";
	private static String hdfs = "hdfs://10.255.248.61:9000";  //這裏配置集羣中master主機IP和端口號


	/**
	 * MapReduceBase類:實現了Mapper和Reducer接口的基類(其中的方法只是實現接口,而未作任何事情)
	 * Mapper接口:
	 * WritableComparable接口:實現WritableComparable的類可以相互比較。所有被用作key的類應該實現此接口。
	 * Reporter 則可用於報告整個應用的運行進度,本例中未使用。 
	 * 
	 */
	public static class Map extends MapReduceBase implements
	Mapper<LongWritable, Text, Text, IntWritable>
	{
		/**
		 * LongWritable, IntWritable, Text 均是 Hadoop 中實現的用於封裝 Java 數據類型的類,這些類實現了WritableComparable接口,
		 * 都能夠被串行化從而便於在分佈式環境中進行數據交換,你可以將它們分別視爲long,int,String 的替代品。
		 */
		private final static IntWritable one = new IntWritable(1);
		private Text word = new Text();

		/**
		 * Mapper接口中的map方法:
		 * void map(K1 key, V1 value, OutputCollector<K2,V2> output, Reporter reporter)
		 * 映射一個單個的輸入k/v對到一箇中間的k/v對
		 * 輸出對不需要和輸入對是相同的類型,輸入對可以映射到0個或多個輸出對。
		 * OutputCollector接口:收集Mapper和Reducer輸出的<k,v>對。
		 * OutputCollector接口的collect(k, v)方法:增加一個(k,v)對到output
		 */
		public void map(LongWritable key, Text value,
				OutputCollector<Text, IntWritable> output, Reporter reporter)
						throws IOException
		{
			String line = value.toString();
			StringTokenizer tokenizer = new StringTokenizer(line);
			while (tokenizer.hasMoreTokens())
			{
				word.set(tokenizer.nextToken());
				output.collect(word, one);
			}
		}
	}
	public static class Reduce extends MapReduceBase implements
	Reducer<Text, IntWritable, Text, IntWritable>
	{
		public void reduce(Text key, Iterator<IntWritable> values,
				OutputCollector<Text, IntWritable> output, Reporter reporter)
						throws IOException
		{
			int sum = 0;
			while (values.hasNext())
			{
				sum += values.next().get();
			}
			output.collect(key, new IntWritable(sum));
		}
	}


	public static void main(String[] args) throws Exception
	{
		/**
		 * JobConf:map/reduce的job配置類,向hadoop框架描述map-reduce執行的工作
		 * 構造方法:JobConf()、JobConf(Class exampleClass)、JobConf(Configuration conf)等
		 */
		JobConf conf = new JobConf(WordCount.class);
		conf.setJobName("wordcount");          //設置一個用戶定義的job名稱

		conf.set("fs.default.name", hdfs);

		conf.setOutputKeyClass(Text.class);    //爲job的輸出數據設置Key類
		conf.setOutputValueClass(IntWritable.class);  //爲job輸出設置value類
		conf.setMapperClass(Map.class);        //爲job設置Mapper類
		conf.setCombinerClass(Reduce.class);      //爲job設置Combiner類
		conf.setReducerClass(Reduce.class);        //爲job設置Reduce類
		conf.setInputFormat(TextInputFormat.class);    //爲map-reduce任務設置InputFormat實現類
		conf.setOutputFormat(TextOutputFormat.class);  //爲map-reduce任務設置OutputFormat實現類
		/**
		 * InputFormat描述map-reduce中對job的輸入定義
		 * setInputPaths():爲map-reduce job設置路徑數組作爲輸入列表
		 * setInputPath():爲map-reduce job設置路徑數組作爲輸出列表
		 */
		
		//設置輸入輸出文件路徑     
		FileSystem fs = FileSystem.get(conf);
		
		Path inputPath = new Path(inPath);
		if(fs.exists(inputPath)) {
		FileInputFormat.setInputPaths(conf, inputPath);
		}
		
		Path outputPath = new Path(outPath);
		fs.delete(outputPath, true);
		
		
		FileOutputFormat.setOutputPath(conf, outputPath);
		
		
		JobClient.runJob(conf);        //運行一個job
	}
}
 運行後refreshHDFS文件系統,可以得到輸出文件的信息:

 
 
在windows系統下進行MapReduce開發需要不小功夫的配置,好了,第一個wordCount程序已經成功編譯了,下面就可以正式開始功能程序的編寫啦! 望每天進步一點!




 
 

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