天天看点

Hadoop的序列化和数据类型

接口

serialization,结构化对象转化为字节流

deserialization,字节流转化为结构化对象

序列化在分布式数据处理的两大领域经常出现:进程间通信和永久存储。

Hadoop使用自己的序列化格式Writable,它格式紧凑,速度快,但很难用Java以外的语言进行扩展和使用。

序列化和反序列化函数:

// 返回b的序列化字节序列
    private static byte[] serialize(Writable b) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        DataOutputStream dataout = new DataOutputStream(out);
        b.write(dataout);
        dataout.close();
        return out.toByteArray();
    }
    private static byte[] deserialize(Writable b, byte[] bytes) throws IOException {
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        DataInputStream datain = new DataInputStream(in);
        b.readFields(datain);
        datain.close();
        return bytes;
    }
           

在Hadoop中所有的key/value类型必须实现Writable接口,它有两个方法,分别用于读(反序列化)和写(序列化):

package org.apache.hadoop.io;

import java.io.DataOutput;
import java.io.DataInput;
import java.io.IOException;

public interface Writable {
    void write(DataOutput out) throws IOException;
    void readFields(DataInput in) throws IOException;
}
           

在MapReduce过程中需要基于key进行反复的排序,任意key类型,都必须实现Comparable接口。

public interface Comparable<T> {
    public int compareTo(T o);
}
           

WritableComparable继承了Writable和Comparable:

public interface WritableComparable<T> extends Writable, Comparable<T> { }
           

所以,一些类型,比如IntWritable实现WritableComparable就可以了。

Hadoop提供的一个优化接口是继承自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);

}
           

该接口允许其实现直接比较数据流的记录,无须先把数据流反序列化为对象。

有点复杂,再说。

由于需要序列化和反序列化,对java对象需要重写以下几个方法:

equals方法

hashCode方法

toString方法

默认的无参构造,为了方便反射进行创建对象

基本数据类型

Writable类对Java基本数据类型提供封装,short和char除外(两者可以存储在IntWritable中)。所有的封装包含get()和set()两个方法用于读取或设置封装的值。

Java基本类型 Writable实现 序列化大小(字节)
boolean BooleanWritable 1
byte ByteWritable 1
int IntWritable 4
VintWritable 1~5
float FloatWritable 4
long LongWritable 8
VlongWritable 1~9
double DoubleWritable 8

Text是针对utf-8序列的Writable类。一般可以认为它等价于java.lang.String的Writable。

NullWritable是一个非常特殊的Writable类型,序列化不包含任何字符,仅仅相当于个占位符。你在使用mapreduce时,key或者value在无需使用时,可以定义为NullWritable。

ObjectWritable和GenericWritable。

在org.apache.hadoop.io包中,有4个集合类:ArrayWritable,TwoDArrayWritable,MapWritable和SortedMapWritable。

对于自定义Comparator类型,需要以下几个步骤:

1、 推荐Comparator类定义在数据类型内部,静态内部类。实现WritableComparator类。

2、 重写默认无参构造方法,方法内必须调用父类有参构造方法

3、 重载父类的compare方法,依据具体功能进行重写。

4、 向WritableComparator类中注册自定义的Comparator类。

参照IntWritable的实现。