Hadoop基于DataInput和DataOutput实现了简单、高效的序列化协议,而Writable接口定义了Hadoop序列化的方法,MapReduce框架中的不论什么键值类型都实现了该接口,比方IntWritable、LongWritable等,具体的类关系见下图:

通过上图可以发现,MapReduce中经常使用的键值类型都没有直接实现Writable接口,而是实现了该接口的子接口WritableComparable,该子接口还继承了Comparable接口,这意味着实现类除了可以序列化和发序列化外,还可以彼此进行比較,这是由于当这些类做为键在MapReduce中使用时,在排序阶段须要对其进行比較排序。但这并非说假设实现自己定义的序列化类时,必须实现WritableComparable接口,仅当自己定义的序列化类也用作键时才必须实现该接口,假设仅是做为值使用的话,仅实现Writable接口就可以。

当自己定义的序列化类用做键时,须要考虑到在依据键进行分区时经经常使用到hashCode()方法,因此须要确保该方法在不同的JVM实例中返回同样的结果,而Object对象中默认的hashCode()方法不可以满足该特性,所以在实现自己定义类时须要重写hashCode()方法,而假设两个对象依据equals()方法是相等的,那么二者的hashCode()返回值也必须同样,因此在重写hashCode()的时候,有必要重写equals(Object obj)方法。

除了上图中实现WritableComparable的类外,还有若干类直接实现了Writable接口,比方ObjectWritable,一个多态的Writable,该类不使用Writable封装就行处理数组、字符串和其他Java基本类型。还有Writable集合类:ArrayWritable、EnumSetWritable、MapWritable、TwoDArrayWritable、SortedMapWritable。当中ArrayWritable是对同样Writable类型的数组的封装,也就是该类中Writable的类型必须同样,是IntWritable都是IntWritable,不能既有IntWritable也有LongWritable。TwoDArrayWritable是对二维数组即矩阵的封装,同样该类中Writable的类型也必须同样。EnumSetWritable是对EnumSet封装的Writable,MapWritable实现了Map<Writable,Writable>接口,SortedMapWritable实现了SortedMap<WritableComparable,Writable>接口,二者当然也都实现了Writable接口,在二者的内部实现中,使用Byte类型指示指定的类型,因此在一个Map实例中最多仅仅能有127个不同的类:

/* Class to id mappings */@VisibleForTestingMap<Class, Byte> classToIdMap = new ConcurrentHashMap<Class, Byte>();/* Id to Class mappings */@VisibleForTestingMap<Byte, Class> idToClassMap = new ConcurrentHashMap<Byte, Class>();

如今通过分析IntWritable和Text的源码来学习怎样编写Writable以及WritableComparable,首先是IntWritable的源码:

public class IntWritable implements WritableComparable<IntWritable> {private int value;public IntWritable() {}public IntWritable(int value) { set(value); }/** Set the value of this IntWritable. */public void set(int value) { this.value = value; }/** Return the value of this IntWritable. */public int get() { return value; }@Override
//重写Writable中的readFields(DataInput in)
public void readFields(DataInput in) throws IOException {value = in.readInt();}@Override//重写Writable中的write(DataOutput out)public void write(DataOutput out) throws IOException {out.writeInt(value);}/** Returns true if <code>o</code> is a IntWritable with the same value. */@Overridepublic boolean equals(Object o) {if (!(o instanceof IntWritable))return false;IntWritable other = (IntWritable)o;return this.value == other.value;}@Overridepublic int hashCode() {return value;}/** Compares two IntWritables. */@Override//重写Comparable接口中的compareTo方法public int compareTo(IntWritable o) {int thisValue = this.value;int thatValue = o.value;return (thisValue<thatValue ? -1 : (thisValue==thatValue ? 0 : 1));}@Overridepublic String toString() {return Integer.toString(value);}//此处省略了继承自WritableComparator的内部类Comparatorstatic {                                        // register this comparatorWritableComparator.define(IntWritable.class, new Comparator());}
}

IntWritable的源码相对来说还是比較简单的,除了实现接口中的方法外,还重写了hashCode、equals和toString方法,这也是要注意的一点。其次是Text类,Text将字符串存储为标准UTF8编码,提供了在字节层次序列化、反序列化和比較字符串的方法,比方decode(byte[]utf8)、encode(String string)、readFields(DataInput in)、write(DataOutput out)等。该类除了实现WritableComparable外,还继承自BinaryComparable抽象类,当中实现的方法例如以下:

private byte[] bytes;
private int length;
@Override
public void readFields(DataInput in) throws IOException {//从输入流中读取整数值,很多其他工具方法可參考WritableUtils工具类int newLength = WritableUtils.readVInt(in);
setCapacity(newLength, false);
//向bytes中读入长度为newLength的数据in.readFully(bytes, 0, newLength);length = newLength;}
@Override
public void write(DataOutput out) throws IOException {WritableUtils.writeVInt(out, length);out.write(bytes, 0, length);}
@Override
public int compareTo(BinaryComparable other) {if (this == other)return 0;return WritableComparator.compareBytes(getBytes(), 0, getLength(),other.getBytes(), 0, other.getLength());}

总结IntWritable和Text类的实现,可以据此实现自定的WritableComparable,以下就是一个简单的演示样例。在该演示样例中使用name和age做为联合键,仅仅有在二者都同样的情况下才觉得是一个对象。

public class CompositeWritable implements WritableComparable<CompositeWritable>{private String name;private int age;public CompositeWritable(){}public CompositeWritable(String name, int age){set(name, age);}@Overridepublic void readFields(DataInput in) throws IOException {name = in.readUTF();age = in.readInt();}@Overridepublic void write(DataOutput out) throws IOException {out.writeUTF(name);out.writeInt(age);}@Overridepublic int compareTo(CompositeWritable o) {int cmp = name.compareTo(o.getName());if(cmp != 0)return cmp;return age < o.getAge()? -1:(age == o.getAge()? 0 : 1);}@Overridepublic boolean equals(Object o) {if(o instanceof CompositeWritable){CompositeWritable other = (CompositeWritable)o;return this.name.equals(other.name) && this.age == other.age;}return false;}@Overridepublic int hashCode() {return name.hashCode() + age;}@Overridepublic String toString() {   return name + "\t" + age;}public void set(String name, int age){this.name = name;this.age = age;}public String getName(){return this.name;}public int getAge(){return this.age;}
}

转载于:https://www.cnblogs.com/mfrbuaa/p/4278524.html

Hadoop-2.4.1学习之Writable及事实上现相关推荐

  1. hadoop hive hbase 入门学习 (二)

    hadoop 自学系列                hadoop hive hbase 入门学习 (一) hadoop安装.hdfs学习及mapreduce学习 hadoop 软件下载 (hadoo ...

  2. 三维点云学习(5)5-实现Deeplearning-PointNet-2-classfication

    三维点云学习(5)5-实现Deeplearning-PointNet-2-classfication Github PointNet源码 数据集下载:为40种物体的三维点云数据集 提取码:es14 运 ...

  3. 三维点云学习(5)4-实现Deeplearning-PointNet-1-数据集的批量读取

    三维点云学习(5)4-实现Deeplearning-PointNet-1-数据集的批量读取 Github PointNet源码 数据集下载:为40种物体的三维点云数据集 提取码:es14 因为本人初次 ...

  4. 三维点云学习(9)5-实现RANSAC Registration配准

    三维点云学习(9)5-实现RANSAC Registration配准 参考博客: 机器视觉之 ICP算法和RANSAC算法 三维点云配准 ICP点云配准原理及优化 本章因个人能力有限,大部分代码摘自g ...

  5. Hadoop HDFS源码学习之NameNode部分

    NameNode源码学习 文章目录 NameNode源码学习 一.文件系统目录树(第一关系) 2.1 INode相关类 2.2 快照特性的实现 2.3 FSEditLog类 2.4 FSImage类 ...

  6. Hadoop生态组件-HIVE学习

    本文将Hadoop生态圈中的一个重要组件Hive.内容包括安装,运行测试,使用MySQL存储Hive的matedata, 还包括其他使用Hive的知识,比如数据分区等.本文是本人学习Hive过程中的记 ...

  7. 【转】hadoop深入研究:(十一)——序列化与Writable实现

    原文链接 http://blog.csdn.net/lastsweetop/article/details/9249411 所有源码在github上,https://github.com/lastsw ...

  8. 《Hadoop权威指南》学习笔记(一)

    本博文是我学习<Hadoop权威指南>3.5节的笔记,主要是里面范例程序的实现,部分实现有修改 1 从Hadoop读取数据 首先新建一个文本文件test.txt作为测试 hadoop fs ...

  9. Hadoop大数据平台实践(二):Hadoop生态组件的学习文档

    Hadoop基础组件学习-Yzg-2019-03-06 Hadoop基础组件学习文档.. 1 简介.. 4 HDFS. 5 HDFS读文件.. 6 HDFS写文件.. 7 Mapreduce 8 单词 ...

  10. Hadoop之Sqoop框架学习(笔记19)

    一.Sqoop基础:连接关系型数据库与Hadoop的桥梁 1.1 Sqoop的基本概念 Hadoop正成为企业用于大数据分析的最热门选择,但想将你的数据移植过去并不容易.Apache Sqoop正在加 ...

最新文章

  1. 磁盘I:O 性能指标 以及 如何通过 fio 对nvme ssd,optane ssd, pmem 性能摸底
  2. VMware 虚拟化编程(1) — VMDK/VDDK/VixDiskLib/VADP 概念简析
  3. Rulo扫地机器人app_要买这样的扫地机器人 浦桑尼克扫地机器人评测
  4. python中常用的函数
  5. 段的创建表user_segments
  6. Java正则表达式较验手机号、邮箱
  7. Seaborn——绘制统计图形
  8. java.util.ArrayList
  9. 一张图看懂VnTrader的数据流
  10. 花了 4 天,破解 UNIX 联合创始人 39 年前的密码!
  11. 2017安防市场新趋势:硬件免费 服务收费
  12. P5018 对称二叉树
  13. 怎么把动态ip改成静态ip?
  14. 软件测试:什么是图灵测试
  15. 读取cpu温度的api_读取CPU核心温度
  16. Visual Studio Code快捷指令
  17. Tungsten Fabric入门宝典丨TF组件的七种“武器”
  18. axis webservice 实验
  19. Android免打包多渠道统计如何实现?通用流行框架大全
  20. RF使用技巧--返回值的妙用

热门文章

  1. Jquery easyui 密码两次输入相等的验证
  2. cisco keepalive
  3. 09年最值得期待7大IT收购:思科收购VMware
  4. VS2017设置C++标准
  5. FreeMarker(一)初识
  6. RAC性能分析 - gc buffer busy acquire 等待事件
  7. c++中向任意目录下写文件
  8. Atitit.uml2 api 的编程代码实现设计uml开发 使用eclipse jar java 版本
  9. window.opener=null;window.close(),只支持IE6不支持IE7,IE8的问题
  10. (转)PHP利用Curl、socket、file_get_contents POST数据