一个MapReduce 程序示例 细节决定成败(九):RawComparator

在mr 框架中,用的最普遍的的一个功能就是比较大小。 map输入时按key排序要比较。reduce的shuff /sort 阶段要比较。
所以我们自定义的key类型都是要实现WritableComparator 接口。这个接口中有三个方法需要我们实现。
先看一个简单的自定义key类型 的代码。我们关注其中有一个 compareTo 方法。

点击(此处)折叠或打开

  1. package wordcount;

  2. import java.io.DataInput;
  3. import java.io.DataOutput;
  4. import java.io.IOException;

  5. import org.apache.hadoop.io.WritableComparable;

  6. public class MyKey implements WritableComparable<MyKey> {

  7.         private char c;
  8.         @Override
  9.         public void write(DataOutput out) throws IOException {
  10.                 out.writeChar(c);
  11.         }

  12.         @Override
  13.         public void readFields(DataInput in) throws IOException {
  14.                 c= in.readChar();
  15.         }

  16.         @Override
  17.         public int compareTo(MyKey key) {
  18.                 if(c==key.c)
  19.                         return 0;
  20.                 else if(c> key.c)
  21.                         return 1;
  22.                 else
  23.                         return -1;
  24.         }

  25.         public char getC() {
  26.                 return c;
  27.         }

  28.         public void setC(char c) {
  29.                 this.c = c;
  30.         }
  31.         @Override
  32.         public String toString(){
  33.                 return String.valueOf(this.c);
  34.         }

  35. }
注意观察我们  public   int   compareTo ( MyKey  key )  ; 参数是MyKey类型。 就是是说在调用这个比较的时候要做一个反序列化操作成Mykey 对象再比较的过程。 那在大量数据集的情况下,如何减少比较的开销呢。
能不能不反序列化,直接使用序列化成的byte进行比较呢? 答案是肯定的。我们这次介绍的RawComparator 就是用来做这个的。
在真正写我们自己的代码之前 ,先介绍一个小技巧:那就是写任何hadoop MapReduce可编程组件时,先参考系统自带的默认实现代码。
根据这个习惯,我们找一个系统自带的类型看看源码。那就找IntWritable吧。

点击(此处)折叠或打开

  1. /** A WritableComparable for ints. */
  2. @InterfaceAudience.Public
  3. @InterfaceStability.Stable
  4. public class IntWritable implements WritableComparable<IntWritable> {
  5.   private int value;

  6.   public IntWritable() {}

  7.   public IntWritable(int value) { set(value); }

  8.   /** Set the value of this IntWritable. */
  9.   public void set(int value) { this.value = value; }

  10.   /** Return the value of this IntWritable. */
  11.   public int get() { return value; }

  12.   @Override
  13.   public void readFields(DataInput in) throws IOException {
  14.     value = in.readInt();
  15.   }

  16.   @Override
  17.   public void write(DataOutput out) throws IOException {
  18.     out.writeInt(value);
  19.   }

  20.   /** Returns true iff <code>o</code> is a IntWritable with the same value. */
  21.   @Override
  22.   public boolean equals(Object o) {
  23.     if (!(o instanceof IntWritable))
  24.       return false;
  25.     IntWritable other = (IntWritable)o;
  26.     return this.value == other.value;
  27.   }

  28.   @Override
  29.   public int hashCode() {
  30.     return value;
  31.   }

  32.   /** Compares two IntWritables. */
  33.   @Override
  34.   public int compareTo(IntWritable o) {
  35.     int thisValue = this.value;
  36.     int thatValue = o.value;
  37.     return (thisValue<thatValue ? -1 : (thisValue==thatValue ? 0 : 1));
  38.   }

  39.   @Override
  40.   public String toString() {
  41.     return Integer.toString(value);
  42.   }

  43.   /** A Comparator optimized for IntWritable. */
  44.   public static class Comparator extends WritableComparator {
  45.     public Comparator() {
  46.       super(IntWritable.class);
  47.     }
  48.     
  49.     @Override
  50.     public int compare(byte[] b1, int s1, int l1,
  51.                        byte[] b2, int s2, int l2) {
  52.       int thisValue = readInt(b1, s1);
  53.       int thatValue = readInt(b2, s2);
  54.       return (thisValue<thatValue ? -1 : (thisValue==thatValue ? 0 : 1));
  55.     }
  56.   }

  57.   static { // register this comparator
  58.     WritableComparator.define(IntWritable.class, new Comparator());
  59.   }
  60. }
IntWritable 的例子中,我们得到:
1、把
WritableComparator  当IntWritable的内部类,写到里面,放到一起比较容易找。
2、如何注册一个自定义的WritableComparator。
  此处注意一下,关注static { WritableComparator.define(IntWritable.class,new Comparator())} 的位置。
  为什么是写到IntWritable中,写到Comparator类中可以不? 为什么? (不能写到Comparator中)
那按这个方式,我们写一下MyKey的RawComparator

点击(此处)折叠或打开

  1. package wordcount;

  2. import java.io.DataInput;
  3. import java.io.DataOutput;
  4. import java.io.IOException;

  5. import org.apache.hadoop.io.WritableComparable;
  6. import org.apache.hadoop.io.WritableComparator;
  7. import org.apache.log4j.Logger;

  8. public class MyKey implements WritableComparable<MyKey> {

  9.         private char c;
  10.         @Override
  11.         public void write(DataOutput out) throws IOException {
  12.                 out.writeChar(c);
  13.         }

  14.         @Override
  15.         public void readFields(DataInput in) throws IOException {
  16.                 c= in.readChar();
  17.         }

  18.         @Override
  19.         public int compareTo(MyKey key) {
  20.                 if(c==key.c)
  21.                         return 0;
  22.                 else if(c> key.c)
  23.                         return 1;
  24.                 else
  25.                         return -1;
  26.         }

  27.         public char getC() {
  28.                 return c;
  29.         }

  30.         public void setC(char c) {
  31.                 this.c = c;
  32.         }
  33.         @Override
  34.         public String toString(){
  35.                 return String.valueOf(this.c);
  36.         }

  37.         public static class MyKeyRawComparator extends WritableComparator{

  38.                 Logger log = Logger.getLogger(MyKeyRawComparator.class);
  39.                 public MyKeyRawComparator(){
  40.                         super(MyKey.class);
  41.                 }

  42.                 @Override
  43.                 public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
  44.                         log.info("==============MyKeyRawComparator Used");

  45.                         return super.readUnsignedShort(b1,s1) - super.readUnsignedShort(b2, s2);
  46.                 }

  47.         }
  48.         static{
  49.                 WritableComparator.define(MyKey.class,new MyKeyRawComparator());
  50.         }

  51. }
为了验证我们的RawComparator执行了,在compare方法中加了日志输出。同时也可以验证在什么时候调用了两个key的比较。
我们理解,应该在map 与reduce阶段都会使用到key的比较。下面我们就分别看一下map与reduce的日志输出。
打开浏览器输入 http://xxx.xxx.xxx.xxx:19888/jobhistory 点击对应的job.
mapper的日志 

reducer的日志



通过日志,验证了我们的预期。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30066956/viewspace-2112283/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/30066956/viewspace-2112283/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值