最近在學習雲計算,研究Haddop框架,費了一整天時間將Hadoop在Linux下完全運行起來,看到官方的map-reduce的demo程序WordCount,仔細研究了一下,算做入門了。
運行方法:
假設:
/home/cq/wordcount/input - 是 HDFS 中的輸入路徑
/home/cq/wordcount/output - 是 HDFS 中的輸出路徑
用示例文本文件做爲輸入:
$ bin/hadoop fs -ls /home/cq/wordcount/input/
/home/cq /wordcount/input/file01
/home/cq /wordcount/input/file02
$ bin/hadoop fs -cat /home/cq/wordcount/input/file01
Hello World Bye World
$ bin/hadoop dfs -cat /home/cq/wordcount/input/file02
Hello Hadoop Goodbye Hadoop
運行應用程序:
$ bin/hadoop jar /*/WordCount /home/cq/wordcount/input /home/cq/wordcount/output
輸出是:
$ bin/hadoop dfs -cat /home/cq/wordcount/output/part-00000
Bye 1
Goodbye 1
Hadoop 2
Hello 2
World 2
詳解:
其實WordCount並不難,只是一下子接觸到了很多的API,有一些陌生,還有就是很傳統的開發相比,map-reduce確實是一種新的編程理 念,爲了讓各位新手少走彎路,我將WordCount中的很多API都做了註釋,其實這些方法搞明白了以後程序就很簡單了,無非就是將一句話分詞,先用 map處理再用reduce處理,最後再main函數中設置一些信息,然後run(),程序就結束了。好了,不廢話,直接上代碼:
package com.felix;
import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;
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 by Felix
* @author Hadoop Dev Group
*/
publicclass WordCount
{
/**
* MapReduceBase類:實現了Mapper和Reducer接口的基類(其中的方法只是實現接口,而未作任何事情)
* Mapper接口:
* WritableComparable接口:實現WritableComparable的類可以相互比較。所有被用作key的類應該實現此接口。
* Reporter 則可用於報告整個應用的運行進度,本例中未使用。
*
*/
publicstaticclass Map extends MapReduceBase implements
Mapper<LongWritable, Text, Text, IntWritable>
{
/**
* LongWritable, IntWritable, Text 均是 Hadoop 中實現的用於封裝 Java 數據類型的類,這些類實現了WritableComparable接口,
* 都能夠被串行化從而便於在分佈式環境中進行數據交換,你可以將它們分別視爲long,int,String 的替代品。
*/
privatefinalstatic 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
*/
publicvoid 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);
}
}
}
publicstaticclass Reduce extends MapReduceBase implements
Reducer<Text, IntWritable, Text, IntWritable>
{
publicvoid 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));
}
}
publicstaticvoid 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.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設置路徑數組作爲輸出列表
*/
FileInputFormat.setInputPaths(conf, new Path(args[ 0 ]));
FileOutputFormat.setOutputPath(conf, new Path(args[ 1 ]));
JobClient.runJob(conf); //運行一個job
轉載自http://hi.baidu.com/whyang2006/item/436a720c4e15a013addc70c4