hadoop AbstractMapWritable及其实现类是怎样的

67次阅读
没有评论

共计 4439 个字符,预计需要花费 12 分钟才能阅读完成。

hadoop AbstractMapWritable 及其实现类是怎样的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面丸趣 TV 小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

     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 对象。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注丸趣 TV 行业资讯频道,感谢您对丸趣 TV 的支持。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-17发表,共计4439字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)