Hadoop Writable机制

为了支持以上这些特性,Hadoop引入org.apache.hadoop.io.Writable接口,作为所有可序列化对象必须实现的接口,其类图如图3-2所示。

加载中...
 

Writable机制紧凑、快速(但不容易扩展到Java以外的语言,如C、Python等)。和java.io.Serializable不同,Writable接口不是一个说明性接口,它包含两个方法:
public interface Writable {
   /**
    * 输出(序列化)对象到流中
    * @param out DataOuput流,序列化的结果保存在流中
    * @throws IOException
    */
   void write(DataOutput out) throws IOException;

   /**
    * 从流中读取(反序列化)对象
    * 为了效率,请尽可能复用现有的对象
    * @param in DataInput流,从该流中读取数据
    * @throws IOException
    */
   void readFields(DataInput in) throws IOException;
}

Writable.write()方法用于将对象状态写入二进制的DataOutput中,反序列化的过程由readFields()从DataInput流中读取状态完成。下面是一个例子:
public class Block implements Writable, Comparable<Block>, Serializable {
   ……
   private long blockId;
   private long numBytes;
   private long generationStamp;
   ……
   public void write(DataOutput out) throws IOException {
      out.writeLong(blockId);
      out.writeLong(numBytes);
      out.writeLong(generationStamp);
   }

   public void readFields(DataInput in) throws IOException {
      this.blockId = in.readLong();
      this.numBytes = in.readLong();
      this.generationStamp = in.readLong();
      if (numBytes < 0) {
         throw new IOException("Unexpected block size: " + numBytes);
      }
   }
   ……
}

这个例子使用的是前面分析Java序列化机制的Block类,Block实现了Writable接口,即需要实现write()方法和readFields()方法,这两个方法的实现都很简单:Block有三个成员变量,write()方法简单地把这三个变量写入流中,而readFields()则从流中依次读入这些数据,并做必要的检查。

Hadoop序列化机制中还包括另外几个重要接口:WritableComparable、RawComparator和WritableComparator。

WritableComparable,顾名思义,它提供类型比较的能力,这对MapReduce至关重要。该接口继承自Writable接口和Comparable接口,其中Comparable用于进行类型比较。ByteWritable、IntWritable、DoubleWritable等Java基本类型对应的Writable类型,都继承自WritableComparable。

效率在Hadoop中非常重要,因此HadoopI/O包中提供了具有高效比较能力的RawComparator接口。RawComparator和WritableComparable类图如图3-3所示。

RawComparator接口允许执行者比较流中读取的未被反序列化为对象的记录,从而省去了创建对象的所有开销。其中,compare()比较时需要的两个参数所对应的记录位于字节数组b1和b2的指定开始位置s1和s1,记录长度为l1和l2,代码如下:
public interface RawComparator<T>extends
Comparator<T> {
   public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2);
}

以IntWritable为例,它的RawComparator实现中(WritableComparator是一个辅助类,实现了RawComparator接口),compare()方法通过readInt()直接在字节数组中读入需要比较的两个整数,然后输出Comparable接口要求的比较结果。值得注意的是,该过程中compare()方法避免使用IntWritable对象,从而避免了不必要的对象分配。相关代码如下:
public static class Comparator extends WritableComparator {
   ……
   public int compare(byte[] b1, int s1, int l1,
                      byte[] b2, int s2, int l2) {
      int thisValue = readInt(b1, s1);
      int thatValue = readInt(b2, s2);
      return (thisValue<thatValue ? -1 : (thisValue==thatValue ? 0 : 1));
   }
   ……
}

WritableComparator是RawComparator对WritableComparable类的一个通用实现。它提供两个主要功能。首先,提供了一个RawComparator的compare()默认实现,该实现从数据流中反序列化要进行比较的对象,然后调用对象的compare()方法进行比较(这些对象都是Comparable的)。其次,它充当了RawComparator实例的一个工厂方法,例如,可以通过如下代码获得IntWritable的RawComparator:
RawComparator<IntWritable>comparator=
   WritableComparator.get(IntWritable.class);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值