-
为了支持以上这些特性,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);
Hadoop Writable机制
最新推荐文章于 2020-01-27 11:42:42 发布