最近在学习云计算,研究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(),程序就结束了。好了,不废话,直接上代码:



Java代码
  1. package  com.felix;  


  2. import  java.io.IOException;  

  3. import  java.util.Iterator;  

  4. import  java.util.StringTokenizer;  


  5. import  org.apache.hadoop.fs.Path;  

  6. import  org.apache.hadoop.io.IntWritable;  

  7. import  org.apache.hadoop.io.LongWritable;  

  8. import  org.apache.hadoop.io.Text;  

  9. import  org.apache.hadoop.mapred.FileInputFormat;  

  10. import  org.apache.hadoop.mapred.FileOutputFormat;  

  11. import  org.apache.hadoop.mapred.JobClient;  

  12. import  org.apache.hadoop.mapred.JobConf;  

  13. import  org.apache.hadoop.mapred.MapReduceBase;  

  14. import  org.apache.hadoop.mapred.Mapper;  

  15. import  org.apache.hadoop.mapred.OutputCollector;  

  16. import  org.apache.hadoop.mapred.Reducer;  

  17. import  org.apache.hadoop.mapred.Reporter;  

  18. import  org.apache.hadoop.mapred.TextInputFormat;  

  19. import  org.apache.hadoop.mapred.TextOutputFormat;  

  20. /**

  21. *

  22. * 描述:WordCount explains by Felix

  23. * @author Hadoop Dev Group

  24. */

  25. publicclass  WordCount  

  26. {  


  27. /**

  28.     * MapReduceBase类:实现了Mapper和Reducer接口的基类(其中的方法只是实现接口,而未作任何事情)

  29.     * Mapper接口:

  30.     * WritableComparable接口:实现WritableComparable的类可以相互比较。所有被用作key的类应该实现此接口。

  31.     * Reporter 则可用于报告整个应用的运行进度,本例中未使用。

  32.     *

  33.     */

  34. publicstaticclass  Map  extends  MapReduceBase  implements

  35.            Mapper  

  36.    {  

  37. /**

  38.         * LongWritable, IntWritable, Text 均是 Hadoop 中实现的用于封装 Java 数据类型的类,这些类实现了WritableComparable接口,

  39.         * 都能够被串行化从而便于在分布式环境中进行数据交换,你可以将它们分别视为long,int,String 的替代品。

  40.         */

  41. privatefinalstatic  IntWritable one =  new  IntWritable( 1 );  

  42. private  Text word =  new  Text();  


  43. /**

  44.         * Mapper接口中的map方法:

  45.         * void map(K1 key, V1 value, OutputCollector output, Reporter reporter)

  46.         * 映射一个单个的输入k/v对到一个中间的k/v对

  47.         * 输出对不需要和输入对是相同的类型,输入对可以映射到0个或多个输出对。

  48.         * OutputCollector接口:收集Mapper和Reducer输出的对。

  49.         * OutputCollector接口的collect(k, v)方法:增加一个(k,v)对到output

  50.         */

  51. publicvoid  map(LongWritable key, Text value,  

  52.                OutputCollector output, Reporter reporter)  

  53. throws  IOException  

  54.        {  

  55.            String line = value.toString();  

  56.            StringTokenizer tokenizer = new  StringTokenizer(line);  

  57. while  (tokenizer.hasMoreTokens())  

  58.            {  

  59.                word.set(tokenizer.nextToken());  

  60.                output.collect(word, one);  

  61.            }  

  62.        }  

  63.    }  


  64. publicstaticclass  Reduce  extends  MapReduceBase  implements

  65.            Reducer  

  66.    {  

  67. publicvoid  reduce(Text key, Iterator values,  

  68.                OutputCollector output, Reporter reporter)  

  69. throws  IOException  

  70.        {  

  71. int  sum =  0 ;  

  72. while  (values.hasNext())  

  73.            {  

  74.                sum += values.next().get();  

  75.            }  

  76.            output.collect(key, new  IntWritable(sum));  

  77.        }  

  78.    }  


  79. publicstaticvoid  main(String[] args)  throws  Exception  

  80.    {  

  81. /**

  82.         * JobConf:map/reduce的job配置类,向hadoop框架描述map-reduce执行的工作

  83.         * 构造方法:JobConf()、JobConf(Class exampleClass)、JobConf(Configuration conf)等

  84.         */

  85.        JobConf conf = new  JobConf(WordCount. class );  

  86.        conf.setJobName("wordcount" );            //设置一个用户定义的job名称


  87.        conf.setOutputKeyClass(Text.class );     //为job的输出数据设置Key类

  88.        conf.setOutputValueClass(IntWritable.class );    //为job输出设置value类


  89.        conf.setMapperClass(Map.class );          //为job设置Mapper类

  90.        conf.setCombinerClass(Reduce.class );       //为job设置Combiner类

  91.        conf.setReducerClass(Reduce.class );         //为job设置Reduce类


  92.        conf.setInputFormat(TextInputFormat.class );     //为map-reduce任务设置InputFormat实现类

  93.        conf.setOutputFormat(TextOutputFormat.class );   //为map-reduce任务设置OutputFormat实现类


  94. /**

  95.         * InputFormat描述map-reduce中对job的输入定义

  96.         * setInputPaths():为map-reduce job设置路径数组作为输入列表

  97.         * setInputPath():为map-reduce job设置路径数组作为输出列表

  98.         */

  99.        FileInputFormat.setInputPaths(conf, new  Path(args[ 0 ]));  

  100.        FileOutputFormat.setOutputPath(conf, new  Path(args[ 1 ]));  


  101.        JobClient.runJob(conf);         //运行一个job

转载自http://hi.baidu.com/whyang2006/item/436a720c4e15a013addc70c4