Hadoop中WritableComparable 和 comparator
1.WritableComparable
查看HadoopAPI,如图所示:
WritableComparable继承自Writable和java.lang.Comparable接口,是一个Writable也是一个Comparable,也就是说,既可以序列化,也可以比较!
再看看它的实现类,发现BooleanWritable, BytesWritable, ByteWritable, DoubleWritable, FloatWritable, IntWritable, LongWritable, MD5Hash, NullWritable, Record, RecordTypeInfo, Text, VIntWritable, VLongWritable都实现了WritableComparable类!
WritableComparable的实现类之间相互来比较,在Map/Reduce中,任何用作键来使用的类都应该实现WritableComparable接口!
Example:
package cn.roboson.writable; import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException; import org.apache.hadoop.io.WritableComparable; /**
* 1.自定义一个类,继承WritableComparable
* 2.发现有三个未实现的方法,两个是Writable接口的(序列化),一个是Comparable接口的(用来比较)
* 3.自定义比较,这里以counter来作为比较
* @author roboson
*
*/
public class MyWritableComparable implements WritableComparable<MyWritableComparable>{ private int counter;
private long timestamp;
public MyWritableComparable() {
// TODO Auto-generated constructor stub
} public MyWritableComparable(int counter,long timestamp) {
// TODO Auto-generated constructor stub
this.counter = counter;
this.timestamp = timestamp;
} @Override
public void readFields(DataInput in) throws IOException {
// TODO Auto-generated method stub //将输入流中的字节流数据转化为结构化数据
counter = in.readInt();
timestamp = in.readLong();
} @Override
public void write(DataOutput out) throws IOException {
// TODO Auto-generated method stub //讲结构化数据写入输出流
out.writeInt(counter);
out.writeLong(timestamp);
} @Override
public int compareTo(MyWritableComparable other) {
// TODO Auto-generated method stub
int thisValue = this.counter;
int otherValue = other.counter;
return (thisValue < otherValue ? -1 : (thisValue == otherValue ? 0 : 1));
} public int getCounter() {
return counter;
} public void setCounter(int counter) {
this.counter = counter;
} public long getTimestamp() {
return timestamp;
} public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
} public static void main(String[] args) {
MyWritableComparable comparable = new MyWritableComparable(3,4);
MyWritableComparable otherComparable = new MyWritableComparable(4, 5);
int value = comparable.compareTo(otherComparable);
if(value==-1){
System.out.println("comparable<otherComparable");
}else if(value==0){
System.out.println("comparable=otherComparable");
}else{
System.out.println("comparable>otherComparable");
}
}
}
运行结果:
2.RawComparator
对于MapReduce来说,因为中间有个基于键的排序阶段,所以类型的比较是非常重要的。Hadoop中提供了原生的比较接口RawComparator,该接口继承子Java 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); //继承自Comparator的方法
@Override
public int compare(T o1, T o2); @Override
public boolean equals(Object obj);
}
查看HadoopAPI:
该类并非被多数的衍生类所实现,其具体的子类为WritableComparator,多数情况下是作为实现Writable接口的类的内置类,提供序列化字节的比较。如下图说所示:BooleanWritable, BytesWritable, ByteWritable, org.apache.hadoop.io.serializer.DeserializerComparator, DoubleWritable, FloatWritable, IntWritable, JavaSerializationComparator, LongWritable, LongWritable, MD5Hash, NullWritable, RecordComparator, Text, UTF8,都实现了RawComparator,作为其内部类。
而WritableComparator则是其的具体子类。
3.WritableComparator
在《Hadoop权威指南》中,说到这儿,很模糊,只说WritableComparator是对继承自WritableComparable类的RawCompartor类的一个通用实现。让人看着很迷惑,这句话什么意思呢?
首先、在第二个小标题RawComparator中,我门都知道WritableComparator实现了RawComparator这个接口,也就是说,WritableComparator是RawComparator的实现。
其次、是对继承自WritableComparable类的RawComparator的一个通用实现。那么继承自WritableComparable类的RawComparator都有哪些呢?也就是说那些类,继承自WritableComparator,并且实现了RawComparator?在第二个小标题RawComparator中有也都说明清楚了,上面的红色部分!同理,实现了WritableComparable类的在第一个小标题WritableComparable中也有说明,红色部分字体!也就谁说WritableComparator是对BooleanWritable.Comparator, BytesWritable.Comparator, ByteWritable.Comparator, DoubleWritable.Comparator, FloatWritable.Comparator, IntWritable.Comparator, LongWritable.Comparator, MD5Hash.Comparator, NullWritable.Comparator, RecordComparator, Text.Comparator, UTF8.Comparator这些类的一个通用实现!这句话就引出了WritableComparator的两个功能:第一,它提供了对原始compare()方法的一个默认实现。该方法能够饭序列化将流中进行比较的对象,并调用对象的compara()方法。第二,它充当的是RawComparator实例的工厂(已注册Writable的实现)。例如,为了获得IntWratable的comparator,我们直接如下调用:
RawComparator<IntWritable> comparator = WritableComparator.get(IntWratable.class);
再来看看WritableComparator这个类是如何定义的,如下图所示:
WritableComparator类类似于一个注册表,里面记录了所有Comparator类的集合。Comparators成员用一张Hash表记录Key=Class,value=WritableComprator的注册信息.这就是它能够充当RawComparator实例工厂的原因!因为它本省的实现中有意个HashMap集合,HashMap<Class,WritableComparator>根据对应的Class,就能返回一个响应的WritableComparator!
Example:
package cn.roboson.writable; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException; import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.RawComparator;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparator; /**
* 1.通过WritableComparator获得IntWritable类的RawComparator实例
* 2.通过两种方式来比较
* @author roboson
*
*/ public class ComparableFinish { public static void main(String[] args) throws IOException { //创建两个IntWritable来比较
IntWritable writable1 = new IntWritable(163);
IntWritable writable2 = new IntWritable(165); //获得IntWritable的RawComparator实例
RawComparator<IntWritable> intRawComparator = WritableComparator.get(IntWritable.class); //直接比较对象
int value1 =intRawComparator.compare(writable1, writable2); if(value1==-1){
System.out.println("writable1<writable2");
}else if(value1==0){
System.out.println("writable1=writable2");
}else{
System.out.println("writable1>writable2");
} //序列化两个对象,获得其字节流
byte[] byte1 = serizlize(writable1);
byte[] byte2 = serizlize(writable2); //直接通过字符流比较大小
int value2 = intRawComparator.compare(byte1, 0, 4, byte2, 0, 4);
if(value2==-1){
System.out.println("writable1<writable2");
}else if(value2==0){
System.out.println("writable1=writable2");
}else{
System.out.println("writable1>writable2");
}
} public static byte[] serizlize(Writable writable) throws IOException{ //创建一个输出字节流对象
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream dataout = new DataOutputStream(out); //将结构化数据的对象writable写入到输出字节流。
writable.write(dataout);
return out.toByteArray();
} public static byte[] deserizlize(Writable writable,byte[] bytes) throws IOException{ //创建一个输入字节流对象,将字节数组中的数据,写入到输入流中
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
DataInputStream datain = new DataInputStream(in); //将输入流中的字节流数据反序列化
writable.readFields(datain);
return bytes; }
}
运行结果:
关于序列化方面的知识,可以参考我的博客《Hadoop序列化》地址如下:
http://www.cnblogs.com/robert-blue/p/4157768.html
参考博文:
http://blog.csdn.net/keda8997110/article/details/8518255
http://www.360doc.com/content/12/0827/09/9318309_232551844.shtml
Hadoop中WritableComparable 和 comparator的更多相关文章
- Hadoop中Comparator原理
在前面的博文<Hadoop中WritableComparable 和 comparator>中,对于WritableComparator说的不够细致,下面说说具体的实现原理! 1.Writ ...
- Hadoop中Writable类之四
1.定制Writable类型 Hadoop中有一套Writable实现,例如:IntWritable.Text等,但是,有时候可能并不能满足自己的需求,这个时候,就需要自己定制Writable类型. ...
- 022_Hadoop中的数据类型(Writable、WritableComparable、Comparator、RawComparator…)
1. 在hadoop中所有的key/value都必须实现Writable接口,有两个方法,分别用于读(反序列化)和写(序列化)操作.
- 1 weekend110的复习 + hadoop中的序列化机制 + 流量求和mr程序开发
以上是,weekend110的yarn的job提交流程源码分析的复习总结 下面呢,来讲weekend110的hadoop中的序列化机制 1363157985066 13726230503 ...
- Hadoop中Partition深度解析
本文地址:http://www.cnblogs.com/archimedes/p/hadoop-partitioner.html,转载请注明源地址. 旧版 API 的 Partitioner 解析 P ...
- hadoop中实现定制Writable类
Hadoop中有一套Writable实现可以满足大部分需求,但是在有些情况下,我们需要根据自己的需要构造一个新的实现,有了定制的Writable,我们就可以完全控制二进制表示和排序顺序. 为了演示如何 ...
- hadoop中的序列化与Writable接口
本文地址:http://www.cnblogs.com/archimedes/p/hadoop-writable-interface.html,转载请注明源地址. 简介 序列化和反序列化就是结构化对象 ...
- Hadoop中序列化与Writable接口
学习笔记,整理自<Hadoop权威指南 第3版> 一.序列化 序列化:序列化是将 内存 中的结构化数据 转化为 能在网络上传输 或 磁盘中进行永久保存的二进制流的过程:反序列化:序列化的逆 ...
- hadoop中MapReduce多种join实现实例分析
转载自:http://zengzhaozheng.blog.51cto.com/8219051/1392961 1.在Reudce端进行连接. 在Reudce端进行连接是MapReduce框架进行表之 ...
随机推荐
- 购买SSL证书到部署网站遇到的若干问题
作为一个菜鸟,对于SSL证书,我了解不多,只知道用了它网站更安全,所以这次使用SSL证书途中遇到了各方面的各种问题,到今天为止终于全部解决. 一.证书格式 前两天在那什么云上面买了个SSL证书,是Wo ...
- 重新想象 Windows 8.1 Store Apps (76) - 新增控件: SearchBox
[源码下载] 重新想象 Windows 8.1 Store Apps (76) - 新增控件: SearchBox 作者:webabcd 介绍重新想象 Windows 8.1 Store Apps 之 ...
- CMD和AMD
CMD是国内玉伯在开发SeaJS的时候提出来的,属于CommonJS的一种规范,此外还有AMD,其对于的框架是RequireJS. 二者的异同之处: 二者都是异步(Asynchronuous Modu ...
- Sass学习之路(3)——Sass编译
Sass的编译也是在我们使用Sass的时候必须要经过的一个步骤,因为".sass"和".scss"文件并不能直接使用<link>标签引用,最终其实还 ...
- 初学Node(一)国际惯例HelloWorld
简介 没有用过Node,记的这些只是学习的笔记,有什么错的地方,望各位前辈指正. Node是一个服务器端Javascript解释器,依赖于Chrome v8引擎进行代码编译,事件驱动.非阻塞I/O都是 ...
- 解决C#导出excel异常来自 HRESULT:0x800A03EC的方法 .
解决C#导出excel异常来自 HRESULT:0x800A03EC的方法 . xlBook.SaveAs(FilePath,Microsoft.Office.Interop.Excel.XlFi ...
- SharePoint 中关于event receivers的讨论
今天一早,跟几个小伙伴在群里讨论了有关事件触发器的东西,感觉收获颇多,拿出来和大家分享.讨论的内容,主要就是关于事件触发器的同步/异步的设置以及作用. 其实接触SharePoint颇久,对于事件触发器 ...
- Windows 下Apace tomcat
java JDK安装: 1. 官方www.oracle.com 下载jdk 2. 环境变量配置 (1)新建->变量名:JAVA_HOME变量值:C:\Program Files (x86)\Ja ...
- 搭建Android 5.0开发环境
1.Android SDK的安装 下载地址:http://developer.android.com/index.html 访问网站的话请自备梯子 选择:adt-bundle-windows-x86_ ...
- 【读书笔记】iOS-UIWindow-WindowLevel
WindowLevel是UIWindow的一个属性.系统定义的一共有3种. UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal; UIKIT_EX ...