mapreduce实现对key的排序

http://blog.csdn.net/evo_steven/article/details/14521713

最近在学习MapReduce编程遇到很多用MR实现按某一列值排序,或二次排序的类似问题,于是试着用MR实现各种排序问题,最终有点小总结:无需在key对象之外写任何排序函数,MR会完成按key值排序,具体详解如下:

  在这之前要先说一下WritableComparable接口。Writable接口大家可能都知道,它是一个实现了序列化协议的序列化对象。在Hadoop中定义一个结构化对象都要实现Writable接口,使得该结构化对象可以序列化为字节流,字节流也可以反序列化为结构化对象。那WritableComparable接口可序列化并且可比较的接口。MapReduce中所有的key值类型都必须实现这个接口,既然是可序列化的那就必须得实现readFiels()write()这两个序列化和反序列化函数,既然也是可比较的那就必须得实现compareTo()函数,该函数即是比较和排序规则的实现。这样MR中的key值就既能可序列化又是可比较的。下面几符图是API中对WritableComparable接口的解释及其方法,还有一个实现了该接口的对象的列子:



                                                                        图 一 WritableComparable 接口解释

                                                                     图 二 WritableComparable 接口方法

                                                              图 三 自定义对象实现WritableComparable 接口例子

  从图三可以看到自定义的对象实现WritableComparable接口除了实现readFields和write方法之外,还必须得实现compareTo()方法,这也是key值排序的关键,实现了改方法key值之间是可比较可排序的,所以也不用另外写排序函数了。Hadoop提供的数据类型如Text,IntWritable,LongWritable,DoubleWritable和FloatWritable等也都实现了WritableComparable接口。所以我们最开始写wordcount等例子,我们使用Longritable,Text等类型做key值并没有去实现compareTo函数,最后结果也是排序好的,就是因为Hadoop提供的数据类型已经实现了WC接口,已经实现了compareTo函数了。如果你有特殊要求,Text,IntWritable这些类型不能满足你对key值的要求,需要自己新建一个数据对象作为自己的key值类型,那就像上图 图三那样重写一个类实现WritableComparable接口,同时实现compareTo函数,函数内部实现你自己的排序规则,最后reduce的数据就会按key值排序了。

     所以总结上面,hadoop会调用key值类型的compareTo函数按照该函数的要求对key值进行排序。所以你想对哪些列排序就要把哪些列并入到key值对象中,像二次排序那样,要对两列进行排序,两列值都要并入key中,则key成为包含两个属性的复合key,Hadoop 提供的key值可用的类型不能满足要求,那就重写一个对象实现WritableComparable接口(类图三),该对象包含连个属性,并实现compareTo函数,最后会根据key值对两列数据排序,从而实现二次排序。

下面是我自己写的一个

[java]  view plain copy
  1. package sina.dip.logfilter.mr;  
  2.   
  3. import java.io.DataInput;  
  4. import java.io.DataOutput;  
  5. import java.io.IOException;  
  6.   
  7. import org.apache.hadoop.io.Text;  
  8. import org.apache.hadoop.io.WritableComparable;  
  9.   
  10. public class ComplexKey implements WritableComparable<ComplexKey> {  
  11.   
  12.     private Text name;  
  13.   
  14.     private Text value;  
  15.   
  16.     private Text minf;  
  17.   
  18.     public ComplexKey() {  
  19.         this.name = new Text();  
  20.   
  21.         this.value = new Text();  
  22.   
  23.         this.minf = new Text();  
  24.     }  
  25.   
  26.     public ComplexKey(String name, String value, String minf) {  
  27.         this.name = new Text(name);  
  28.   
  29.         this.value = new Text(value);  
  30.   
  31.         this.minf = new Text(minf);  
  32.     }  
  33.   
  34.     public Text getName() {  
  35.         return name;  
  36.     }  
  37.   
  38.     public void setName(Text name) {  
  39.         this.name = name;  
  40.     }  
  41.   
  42.     public Text getValue() {  
  43.         return value;  
  44.     }  
  45.   
  46.     public void setValue(Text value) {  
  47.         this.value = value;  
  48.     }  
  49.   
  50.     public Text getMinf() {  
  51.         return minf;  
  52.     }  
  53.   
  54.     public void setMinf(Text minf) {  
  55.         this.minf = minf;  
  56.     }  
  57.   
  58.     @Override  
  59.     public int compareTo(ComplexKey c) {  
  60.         int compare = 0;  
  61.   
  62.         compare = name.compareTo(c.name);  
  63.         if (compare != 0) {  
  64.             return compare;  
  65.         }  
  66.   
  67.         compare = value.compareTo(c.value);  
  68.         if (compare != 0) {  
  69.             return compare;  
  70.         }  
  71.   
  72.         compare = minf.compareTo(c.minf);  
  73.         if (compare != 0) {  
  74.             return compare;  
  75.         }  
  76.   
  77.         return 0;  
  78.     }  
  79.   
  80.     @Override  
  81.     public void readFields(DataInput in) throws IOException {  
  82.         name.readFields(in);  
  83.   
  84.         value.readFields(in);  
  85.   
  86.         minf.readFields(in);  
  87.     }  
  88.   
  89.     @Override  
  90.     public void write(DataOutput out) throws IOException {  
  91.         name.write(out);  
  92.   
  93.         value.write(out);  
  94.   
  95.         minf.write(out);  
  96.     }  
  97.   
  98. }  





版权声明:本文为博主原创文章,未经博主允许不得转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值