您的位置:首页 > 运维架构

hadoop AbstractMapWritable及其实现类

2014-03-18 00:00 106 查看
AbstractMapWritable作为抽象的Map容器Writable类型,主要是为其实现类MapWritable和SortedMapWritable提供出一套索引表的结构,如下:

Map<Class, Byte> classToIdMap = new ConcurrentHashMap<Class, Byte>()     //id到Class的映射表
Map<Byte, Class> idToClassMap = new ConcurrentHashMap<Byte, Class>(),   //class到Id的映射表


索引表需要添加新的class对象和Id映射关系,势必需要一个新的Id变量,class对象则作为方法形参,如下

private volatile byte newClasses = 0;


有了上面的数据结构,则需要增加一些数据的操作方法,既然AbstractMapWritable基本的数据结构是关于索引表的,自然的会有索引的添加

private synchronized void addToMap(Class clazz, byte id) {
//主要实现功能为对索引id通过两个索引表操作是否存在已存在,索引Id存在但不为形参id则抛异常,否则加入索引信息
}
protected synchronized void addToMap(Class clazz) {
//不存在索引id,且当前索引变量newClasses<127则自动加入索引信息
if (classToIdMap.containsKey(clazz)) {
return;
}
if (newClasses + 1 > Byte.MAX_VALUE) {
throw new IndexOutOfBoundsException("adding an additional class would" +
" exceed the maximum number allowed");
}
byte id = ++newClasses;
addToMap(clazz, id);
}


AbstractMapWritable提供了一个受保护的构造函数

protected AbstractMapWritable() {
this.conf = new AtomicReference<Configuration>();

//添加基础序列化类型的索引信息,索引表能表示的范围只有-127~128种类型
addToMap(ArrayWritable.class,
Byte.valueOf(Integer.valueOf(-127).byteValue()));
addToMap(BooleanWritable.class,
Byte.valueOf(Integer.valueOf(-126).byteValue()));
addToMap(BytesWritable.class,
Byte.valueOf(Integer.valueOf(-125).byteValue()));
addToMap(FloatWritable.class,
Byte.valueOf(Integer.valueOf(-124).byteValue()));
addToMap(IntWritable.class,
Byte.valueOf(Integer.valueOf(-123).byteValue()));
addToMap(LongWritable.class,
Byte.valueOf(Integer.valueOf(-122).byteValue()));
addToMap(MapWritable.class,
Byte.valueOf(Integer.valueOf(-121).byteValue()));
addToMap(MD5Hash.class,
Byte.valueOf(Integer.valueOf(-120).byteValue()));
addToMap(NullWritable.class,
Byte.valueOf(Integer.valueOf(-119).byteValue()));
addToMap(ObjectWritable.class,
Byte.valueOf(Integer.valueOf(-118).byteValue()));
addToMap(SortedMapWritable.class,
Byte.valueOf(Integer.valueOf(-117).byteValue()));
addToMap(Text.class,
Byte.valueOf(Integer.valueOf(-116).byteValue()));
addToMap(TwoDArrayWritable.class,
Byte.valueOf(Integer.valueOf(-115).byteValue()));

// UTF8 is deprecated so we don't support it

addToMap(VIntWritable.class,
Byte.valueOf(Integer.valueOf(-114).byteValue()));
addToMap(VLongWritable.class,
Byte.valueOf(Integer.valueOf(-113).byteValue()));
}


紧接着的是序列化和反序列化方法

序列化:将索引信息写流中

//序列化方法首先写入的是当前索引变量newClasses,然后依次从索引Id范围[1,newClasss]依次写入索引Id+类名的组合
public void write(DataOutput out) throws IOException {

// First write out the size of the class table and any classes that are
// "unknown" classes
//写入索引ID
out.writeByte(newClasses);
/*
**不明白为什么只是写入部分[1~newClasses]的索引信息,而非[-127~newClasses的索引信息],
**猜想可能与子类覆盖其受保护的构造函数有关,因为newClasses默认初始为0
**/
for (byte i = 1; i <= newClasses; i++) {
out.writeByte(i);
out.writeUTF(getClass(i).getName());
}
}


反序列化:从流中构造出索引信息

//主要是根据序列化的结构从流中构造索引信息
public void readFields(DataInput in) throws IOException {

// Get the number of "unknown" classes

newClasses = in.readByte();

// Then read in the class names and add them to our tables

for (int i = 0; i < newClasses; i++) {
byte id = in.readByte();
String className = in.readUTF();
try {
//索引信息构造
addToMap(Class.forName(className), id);

} catch (ClassNotFoundException e) {
throw new IOException("can't find class: " + className + " because "+
e.getMessage());
}
}
}


AbstractMapWritable作为MapWritable抽象类并没有涉及到Map<Wirtable,Writable>的键值对操作,而是从抽象层抽象出索引表,其实现类MapWritable和SortedMapWritable则是新增了Map<Wirtable,Writable>变量,不同的之处在于SortedMapWritable是实现了排序了的TreeMap,自身已具有排序功能。

//MapWritable构造函数
public MapWritable() {
super();
this.instance = new HashMap<Writable, Writable>();
}
//SortedMapWritable构造函数
public SortedMapWritable() {
super();
this.instance = new TreeMap<WritableComparable, Writable>();
}

对于新增的成员Map<Wirtable,Writable>自然需要具备一些方法,基本上跟java的map(这里需要维护索引表)方法无异,但对于序列化和反序列化则是在其抽象类的基础上扩展,具体如下

序列化:先调用AbstractMapWritable的序列化方法,在对Map<Wirtable,Writable>的容量序列化,接着对key和value一一序列化

//MapWritable的序列化方法
public void write(DataOutput out) throws IOException {
super.write(out);

// Write out the number of entries in the map

out.writeInt(instance.size());

// Then write out each key/value pair

for (Map.Entry<Writable, Writable> e: instance.entrySet()) {
out.writeByte(getId(e.getKey().getClass()));
e.getKey().write(out);
out.writeByte(getId(e.getValue().getClass()));
e.getValue().write(out);
}
}

反序列化:则按照上诉的结构从流中构造出索引表和Writable对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: