接口
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的实现。