Mapper类详解

来源:互联网 发布:淘宝发布宝贝 压缩包 编辑:程序博客网 时间:2024/06/05 14:31
[java] view plain copy
  1. <span style="font-family:SimSun;font-size:14px;">public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {  
  2.   
  3.   public class Context   
  4.     extends MapContext<KEYIN,VALUEIN,KEYOUT,VALUEOUT> {  
  5.     public Context(Configuration conf, TaskAttemptID taskid,  
  6.                    RecordReader<KEYIN,VALUEIN> reader,  
  7.                    RecordWriter<KEYOUT,VALUEOUT> writer,  
  8.                    OutputCommitter committer,  
  9.                    StatusReporter reporter,  
  10.                    InputSplit split) throws IOException, InterruptedException {  
  11.       super(conf, taskid, reader, writer, committer, reporter, split);  
  12.     }  
  13.   }  
  14.     
  15.   /** 
  16.    * Called once at the beginning of the task. 
  17.    */  
  18.   protected void setup(Context context  
  19.                        ) throws IOException, InterruptedException {  
  20.     // NOTHING  
  21.   }  
  22.   
  23.   /** 
  24.    * Called once for each key/value pair in the input split. Most applications 
  25.    * should override this, but the default is the identity function. 
  26.    */  
  27.   @SuppressWarnings("unchecked")  
  28.   protected void map(KEYIN key, VALUEIN value,   
  29.                      Context context) throws IOException, InterruptedException {  
  30.     context.write((KEYOUT) key, (VALUEOUT) value);  
  31.   }  
  32.   
  33.   /** 
  34.    * Called once at the end of the task. 
  35.    */  
  36.   protected void cleanup(Context context  
  37.                          ) throws IOException, InterruptedException {  
  38.     // NOTHING  
  39.   }  
  40.     
  41.   /** 
  42.    * Expert users can override this method for more complete control over the 
  43.    * execution of the Mapper. 
  44.    * @param context 
  45.    * @throws IOException 
  46.    */  
  47.   public void run(Context context) throws IOException, InterruptedException {  
  48.     setup(context);  
  49.     while (context.nextKeyValue()) {  
  50.       map(context.getCurrentKey(), context.getCurrentValue(), context);  
  51.     }  
  52.     cleanup(context);  
  53.   }  
  54. }</span>  

       Mapper共有setup(),map(),cleanup()和run()四个方法。其中setup()一般是用来进行一些map()前的准备工作,map()则一般承担主要的处理工作,cleanup()则是收尾工作如关闭文件或者执行map()后的K-V分发等。run()方法提供了setup->map->cleanup()的执行模板。从上面run方法可以看出,K/V对是从传入的Context获取的。我们也可以从下面的map方法看出,输出结果K/V对也是通过Context来完成的。至于Context暂且放着。  

我们先来看看三个Mapper子类,它们位src\mapred\org\apache\Hadoop\mapreduce\lib\map:

 1、TokenCounterMapper

[java] view plain copy
  1. <span style="font-family:SimSun;font-size:14px;">public class TokenCounterMapper extends Mapper<Object, Text, Text, IntWritable>{    
  2.             
  3.       private final static IntWritable one = new IntWritable(1);    
  4.       private Text word = new Text();    
  5.           
  6.       @Override    
  7.       public void map(Object key, Text value, Context context    
  8.                       ) throws IOException, InterruptedException {    
  9.         StringTokenizer itr = new StringTokenizer(value.toString());    
  10.         while (itr.hasMoreTokens()) {    
  11.           word.set(itr.nextToken());    
  12.           context.write(word, one);    
  13.         }    
  14.       }    
  15.   } </span>  

       我们看到,对于一个输入的K-V对,它使用StringTokenizer来获取value中的tokens,然后对每一个token,分发出一个<token,one>对,这将在reduce端被收集,同一个token对应的K-V对都会被收集到同一个reducer上,这样我们就可以计算出所有mapper分发出来的以某个token为key的<token,one>的数量,然后只要在reduce函数中加起来,就得到了token的计数。这就是为什么这个类叫做TokenCounterMapper的原因。     

       在MapReduce的“Hello world”:WordCount例子中,我们完全可以直接使用这个TokenCounterMapper作为MapperClass,仅需用job.setMapperClass(TokenCounterMapper.class)进行设置即可。

2.InverseMapper

[java] view plain copy
  1. <span style="font-family:SimSun;font-size:14px;"public class InverseMapper<K, V> extends Mapper<K,V,V,K> {    
  2.         
  3.         
  4.     /** The inverse function.  Input keys and values are swapped.*/    
  5.     @Override    
  6.     public void map(K key, V value, Context context    
  7.                     ) throws IOException, InterruptedException {    
  8.       context.write(value, key);    
  9.   }  </span>  

 这个类更加简单,它紧紧是调换Key和Value,然后直接分发出去。举个例子:数据格式是<某商家,某商品>,我们既可能需要计算一个商家对应的所有商品种类,也可能需要计算某个商品的销售商家数量,后者的情形,就可以使用InverseMapper来达到目的,使得相同商品被分发到相同reducer。       

http://blog.csdn.NET/posa88/article/details/7901304