Hadoop-2.4.1学习之Writable及事实上现
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 */
@VisibleForTesting
Map<Class, Byte> classToIdMap = new ConcurrentHashMap<Class, Byte>();
/* Id to Class mappings */
@VisibleForTesting
Map<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. */
@Override
public boolean equals(Object o) {
if (!(o instanceof IntWritable))
return false;
IntWritable other = (IntWritable)o;
return this.value == other.value;
}
@Override
public 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));
}
@Override
public String toString() {
return Integer.toString(value);
}
//此处省略了继承自WritableComparator的内部类Comparator
static { // register this comparator
WritableComparator.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);
}
@Override
public void readFields(DataInput in) throws IOException {
name = in.readUTF();
age = in.readInt();
}
@Override
public void write(DataOutput out) throws IOException {
out.writeUTF(name);
out.writeInt(age);
}
@Override
public 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);
}
@Override
public boolean equals(Object o) {
if(o instanceof CompositeWritable){
CompositeWritable other = (CompositeWritable)o;
return this.name.equals(other.name) && this.age == other.age;
}
return false;
}
@Override
public int hashCode() {
return name.hashCode() + age;
}
@Override
public 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;
}
}
Hadoop-2.4.1学习之Writable及事实上现的更多相关文章
- eclipse 提交作业到JobTracker Hadoop的数据类型要求必须实现Writable接口
问:在eclipse中的写的代码如何提交作业到JobTracker中的哪?答:(1)在eclipse中调用的job.waitForCompletion(true)实际上执行如下方法 connect() ...
- 开启Hadoop和Spark的学习之路
Hadoop Hadoop是一个由Apache基金会所开发的分布式系统基础架构. 用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力进行高速运算和存储. Hadoop实现了一个 ...
- Hadoop 2.2.0学习笔记20131210
伪分布式单节点安装执行pi失败: [root@server- ~]# ./bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples ...
- Hadoop 2.2.0学习笔记20131209
1.下载java 7并安装 [root@server- ~]# rpm -ivh jdk-7u40-linux-x64.rpm Preparing... ####################### ...
- hadoop自带TestDFSIO学习
hadoop系统中,包含了很多测试工具包,如测试mapreduce系统读写文件系统,有testDFSIO工具 首先安装好hadoop,配置好环境变量 进入share目录下的mapreduce目录下面, ...
- Hadoop学习---Hadoop的HBase的学习
Hbase Hbase的特点: Hbase是bigtable的开源的仿制版本 建立在HDFS之上 可靠性,靠性能 大:一个表可以有上亿行,上百万列 面向列:面向列(族)的存储和权限控制,列(族)独立检 ...
- MR hadoop streaming job的学习 combiner
代码已经拷贝到了公司电脑的: /Users/baidu/Documents/Data/Work/Code/Self/hadoop_mr_streaming_jobs 首先是主控脚本 main.sh 调 ...
- [Spring Data Repositories]学习笔记--使用现有的repository
以下内容是在学习Spring-Data-mongoDB中的Spring Data Repositories时做的一些笔记.备忘! 感觉学习还是看官方的资料比较透彻一些. Spring Data Rep ...
- [Hadoop] Hadoop学习历程 [持续更新中…]
1. Hadoop FS Shell Hadoop之所以可以实现分布式计算,主要的原因之一是因为其背后的分布式文件系统(HDFS).所以,对于Hadoop的文件操作需要有一套全新的shell指令来完成 ...
随机推荐
- 【C语言探索之旅】 第一部分第九课:函数
内容简介 1.课程大纲 2.第一部分第九课:函数 3.第一部分第十课预告: 练习题+习作 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. ...
- POJ 2217 Secretary (后缀数组)
标题效果: 计算两个公共串串最长的字符串的长度. IDEAS: 这两个组合的字符串. 然后直接确定运行后缀数组height 然后,你可以直接扫描一次height .加个是不是在一个串中的推断就能够了. ...
- StackExchange.Redis 使用 - 事件(五)
ConnectionMultiplexer 可以注册如下事件 ConfigurationChanged - 配置更改时 ConfigurationChangedBroadcast - 通过发布订阅更新 ...
- MEF初体验之十:部件重组
一些应用程序被设计成在运行时可以动态改变.例如,一个新的扩展被下载,或者因为其它的多种多样的原因其它的扩展变得不可用.MEF处理这些多样的场景是依赖我们称作重组的功能来实现的,它可已在最初的组合后改变 ...
- Git--Submodule使用
项目模板中通常由前端保持,所以每次更新模板.我也要跟着变化项目. 随着时间的推移,这不是一个方法来找到,老这么维护.大型项目,更多的模板,真的很容易管理和维护. 然后头让我用submodule前端资源 ...
- OGG "Loading data from file to Replicat"table静态数据同步配置过程
OGG "Loading data from file to Replicat"table静态数据同步配置过程 一个.mgr过程 GGSCI (lei1) 3> view p ...
- REST WebService
REST WebService 前置技能 ① 使用maven来管理java项目 这个技能必须点一级,以便快速配置项目. 本文实际上是我学习Spring的过程中搬的官网上的demo,使用maven配置项 ...
- cocos2dx怎样设置ios和Android横屏竖屏的几种方法
cocos2d-x编译到ios上.默认是横屏的,若要改为http://竖屏.不同的ios版本号.方法也会不同 在ios7上或许我们设置好了横竖屏.但到了ios6上或许会变化.以下白白给大家分享一下我的 ...
- 联想G480安装CentOS电缆驱动器
最近.联想G480 32本机安装现场CentOS 6.5. 发现.总是无法使用有线网络. 必须安装必要的驱动,搜集了资料,安装过程例如以下: 1. 必备的软件 安装前,须要下列的软件依赖包. sudo ...
- NFS文件系统配置 和 GLIBC更新
为了配置集群环境,把过程记录一下,方便后续使用 NFS 文件系统 是 network file system 配置好ssh无密码访问 ,各节点为centos6.5 主节点 在文件/etc/expor ...