整套大数据学习资料(视频+笔记)百度网盘无门槛下载:http://www.edu360.cn/news/content?id=3377

4.3.1. Writable 接口

hadoop 花牛 9℃ 0评论

Writable接口定义了两个方法:一个将其状态写到DataOutput二进制流, 另一个从Datalnput二进制流读取状态:

package org.apache.hadoop.io;
import java.io.DataOutput;
import java.io.Datalnput;
import java.io.IOException;
public interface Writable {
    void write(DataOutput out) throws IOException;
    void readFields(Datalnput in) throws IOException;
}

让我们通过一个特殊的Writable类来看看它的具体用途。我们将使用 IntWritable来封装Java int类型。我们可以新建一个对象并使用set()方法来设置它的值:

IntWritable writable = new IntWritable();
writable.set(163);

也可以通过使用一个整数值作为输入参数的构造函数来新建一个对象:

IntWritable writable = new IntWritable(163);

为了检査 IntWritable 的序列化形式,我们在 java.io.DataOutputStream (java.ioDataOutput的一个实现)中加入一个帮助函数来封装java .io.ByteArrayOutputSteam,以便在序列化流中捕捉字节:

public static byte[] serialize(Writable writable) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DataOutputStream dataOut = new DataOutputStream(out);
    writable.write(dataOut);
    dataOut.close();
    return out.toByteArray();
}

一个整数占用4个字节(因为我们使用JUnit4进行声明):

byte[] bytes = serialize(writable);
assertThat(bytes.length, is(4));

每个字节是按照大端顺序写入的(按照java.io.DataOutput接口中的声明,最重要的字节先写到流),并且通过HadoopStringUtils,我们可以看到这些字节的十六进制表示:

assertThat(StringUtils.byteToHexString(bytes), is("000000a3"));

让我们试试反序列化。我们再次新建一个辅助方法,从一个字节数组中读取一个Writable对象:

public static byte[] deserialize(Writable writable, byte[] bytes) throws IOException {
    ByteArrayInputStream in = new ByteArraylnputStream(bytes);
    DatalnputStream dataln = new DatalnputStream(in);
    writable.readFields(dataIn);
    dataln.close();
    return bytes;
}

我们构建了一个新的、空值的IntWritable对象,然后调用 deserialize()方法从我们刚写的输出数据中读取数据。最后,我们看到该值(通过get()方法获取)是原始的数值163:

IntWritable newWritable = new IntWritable();
deserialize(newWritable, bytes);
assertThat(newWritable.get(), is(163));

WritableComparable接口和comparator

IntWritable实现原始的WritableComparable接口,该接口继承自 Writable 和 java.lang.Comparable 接口:

package org.apache.hadoop.io;
    public interface WritableComparable<T> extends Writable, Comparable<T> {
}

对MapReduce来说,类型比较非常重要,因为中间有个基于键的排序阶段。Hadoop提供的一个优化接口是继承自]ava Comparator的RawComparator接口:

package org.apache.hadoop.io;
import java.util.Comparator;
public interface RawComparator<T> extends Comparator<T> {
    public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2);
}

该接口允许其实现直接比较数据流中的记录,无须先把数据流反序列化为对象,这样便避免了新建对象的额外开销。例如,我们根据IntWritable接口实现的comparator实现原始的compare()方法,该方法可以从每个字节数组b1b2中读取给定起始位置(s1s2)以及长度(l1和l2)的一个整数进而直接进行比较。

WritableComparator 是对继承自 WritableComparable 类的RawComparator类的一个通用实现。它提供两个主要功能。第一,它提供了对原始compare()方法的一个默认实现,该方法能够反序列化将在流中进行比较的对象,并调用对象的compare()方法。第二,它充当的是RawComparator实例的工厂(已注册Writable的实现)。例如,为了获得IntHratablecomparator,我们直接如下调用:

RawCompanator<IntWritable> comparator = WritableComparator.get (IntWritable.class);

这个comparator可以用于比较两个IntWritable对象:

IntWritable w1= new IntWritable(163);
IntWritable w2 = new IntWritable(67);
assertThat(comparator.compare(wl, w2), greaterThan(0));

或其序列化表示:

byte[] b1 = serialize(wl);
byte[] b2 = serialize(w2);
assertThat(comparator.compare(bl, 0, bl.length, b2, 0, b2.length), greaterThan(0));

转载请注明:全栈大数据 » 4.3.1. Writable 接口

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址