Hadoop中有一套Writable实现可以满足大部分需求,但是在有些情况下,我们需要根据自己的需要构造一个新的实现,有了定制的Writable,我们就可以完全控制二进制表示和排序顺序。

为了演示如何新建一个定制的writable类型,我们需要写一个表示一对字符串的实现:

blic class TextPair implements WritableComparable<TextPair> {
private Text first;
private Text second; public TextPair() {
set(new Text(), new Text());
} public TextPair(String first, String second) {
set(new Text(first), new Text(second));
} public TextPair(Text first, Text second) {
set(first, second);
} public void set(Text first, Text second) {
this.first = first;
this.second = second;
} public Text getFirst() {
return first;
} public Text getScond() {
return second;
} public void write(DataOutput out) throws IOException {
first.write(out);
second.write(out);
} public void readFields(DataInput in) throws IOException {
first.readFields(in);
second.readFields(in);
} public int hashCode() {
return first.hashCode() * 163 + second.hashCode();
} public boolean equals(Object o) {
if(o instanceof TextPair) {
TextPair tp = (TextPair)o;
return first.equals(tp.first) && second.equals(tp.second);
}
return false;
} public String toString() {
return first + "\t" + second;
} public int compareTo(TextPair tp) {
int cmp = first.compareTo(tp.first);
if(cmp != 0) {
return cmp;
}
return second.compareTo(tp.second);
}
}

为速度实现一个RawComparator

还可以进一步的优化,当作为MapReduce里的key,需要进行比较时,因为他已经被序列化,想要比较他们,那么首先要先反序列化成一个对象,然后再调用compareTo对象进行比较,但是这样效率太低了,有没有可能可以直接比较序列化后的结果呢,答案是肯定的,可以。

RawComparator接口允许执行者比较流中读取的未被反序列化为对象的记录,从而省去了创建对象的所有的开销,其中,compare() 比较时需要的两个参数所对应的记录位于字节数组b1和b2指定开始位置s1和s2,记录长度为l1和l2,代码如下:

public interface RawComparator<T> extends Comparator<T> {
public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2);
}

以IntWritable为例,它的RawComparator实现中,compare() 方法通过readInt()直接在字节数组中读入需要比较的两个整数,然后输出Comparable接口要求的比较结果。

值得注意的是,该过程中compare()方法避免使用IntWritable对象,从而避免了不必要的对象分配,相关代码如下:

  /** A Comparator optimized for IntWritable. */
public static class Comparator extends WritableComparator {
public Comparator() {
super(IntWritable.class);
} public int compare(byte[] b1, int s1, int l1,
byte[] b2, int s2, int l2) {
int thisValue = readInt(b1, s1);
int thatValue = readInt(b2, s2);
return (thisValue<thatValue ? -1 : (thisValue==thatValue ? 0 : 1));
}
}

Writablecomparator是RawComparator对WritableComparable类的一个通用实现,它提供两个主要功能:

1、提供了一个RawComparator的compare()默认实现,该实现从数据流中反序列化要进行比较的对象,然后调用对象的compare()方法进行比较

2、它充当了RawComparator实例的一个工厂方法。例如,可以通过下面的代码获得IntWritable的RawComparator:

RawComparator<IntWritable> comparator = WritableComparator.get(IntWritable.class);

我们只需要把EmploeeWritable的序列化后的结果拆成成员对象,然后比较成员对象即可:

class Comparator extends WritableComparator {
private static final Text.Comparator TEXT_COMPARATOR = new Text.Comparator();
public Comparator() {
super(TextPair.class);
}
public int compara(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
try {
int firstL1 = WritableUtils.decodeVIntSize(b1[s1]) + readVInt(b1, s1);
int firstL2 = WritableUtils.decodeVIntSize(b2[s2]) + readVInt(b2, s2);
int cmp = TEXT_COMPARATOR.compare(b1, s1, firstL1, b2, s2, firstL2);
if(cmp != 0) {
return cmp;
}
return TEXT_COMPARATOR.compare(b1, s1 + firstL1, l1 - firstL1, b2, s2 + firstL2, l2 - firstL2);
} catch(IOException e) {
throw new IllegalArgumentException(e);
}
}
}

定制comparators

有时候,除了默认的comparator,你可能还需要一些自定义的comparator来生成不同的排序队列,看一下下面这个示例:

    public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
try {
int firstL1 = WritableUtils.decodeVIntSize(b1[s1])+ readVInt(b1, s1);
int firstL2 = WritableUtils.decodeVIntSize(b2[s2])+ readVInt(b2, s2);
return TEXT_COMPARATOR.compare(b1, s1, firstL1, b2, s2, firstL2);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
} public int compare(WritableComparable a, WritableComparable b) {
if(a instanceof Textpair && b instanceof TextPair) {
return ((TextPair) a).first.compareTo(((TextPair) b).first);
}
return super.compare(a, b);
}

hadoop中实现定制Writable类的更多相关文章

  1. 定制Writable类

    以IntWritable为例介绍,定制writable的步骤 //继承 WritableComparable接口(继承了writable接口和comparable接口) public class In ...

  2. Hadoop中序列化与Writable接口

    学习笔记,整理自<Hadoop权威指南 第3版> 一.序列化 序列化:序列化是将 内存 中的结构化数据 转化为 能在网络上传输 或 磁盘中进行永久保存的二进制流的过程:反序列化:序列化的逆 ...

  3. Hadoop中Writable类之四

    1.定制Writable类型 Hadoop中有一套Writable实现,例如:IntWritable.Text等,但是,有时候可能并不能满足自己的需求,这个时候,就需要自己定制Writable类型. ...

  4. Hadoop中Writable类之二

    1.ASCII.Unicode.UFT-8 在看Text类型的时候,里面出现了上面三种编码,先看看这三种编码: ASCII是基于拉丁字母的一套电脑编码系统.它主要用于显示现代英语和其他西欧语言.它是现 ...

  5. hadoop中典型Writable类详解

    本文地址:http://www.cnblogs.com/archimedes/p/hadoop-writable.html,转载请注明源地址. Hadoop将很多Writable类归入org.apac ...

  6. hadoop中的序列化与Writable类

    本文地址:http://www.cnblogs.com/archimedes/p/hadoop-writable-class.html,转载请注明源地址. hadoop中自带的org.apache.h ...

  7. Hadoop中Writable类

    1.Writable简单介绍 在前面的博客中,经常出现IntWritable,ByteWritable.....光从字面上,就可以看出,给人的感觉是基本数据类型 和 序列化!在Hadoop中自带的or ...

  8. hadoop中的序列化与Writable接口

    本文地址:http://www.cnblogs.com/archimedes/p/hadoop-writable-interface.html,转载请注明源地址. 简介 序列化和反序列化就是结构化对象 ...

  9. Hadoop中Partition的定制

    1.解析Partition Map的结果,会通过partition分发到Reducer上,Reducer做完Reduce操作后,通过OutputFormat,进行输出,下面我们就来分析参与这个过程的类 ...

随机推荐

  1. Android之 内容提供器(1)——使用内容提供器访问其它程序共享的数据

    (下面内容是阅读郭霖大神的<第一行代码>总结的) 1 概述 内容提供器是Android实现跨程序共享数据的标准方式. 内容提供器的的使用方法有两种, 一是使用已有的内容提供器对其他程序的数 ...

  2. iOS 9音频应用播放音频之音量设置与声道设置

    iOS 9音频应用播放音频之音量设置与声道设置 iOS 9音频应用音量设置 音量又称响度.音强,是指人耳对所听到的声音大小强弱的主观感受,其客观评价尺度是声音的振幅大小.在iOS 9音频应用的应用中, ...

  3. ubuntu 远程登录(ssh)

    Ubuntu下通过SSH远程登录服务器的方法 首先在服务器上安装ssh的服务器端. $ sudo aptitude install openssh-server 启动ssh-server. $ /et ...

  4. CF617/E XOR and Favorite Number

    题目链接:http://codeforces.com/contest/617/problem/E 题意:给出一个长度为n(1e5)的序列,有m(1e5)次操作,每次操作选择一个L-R区间,然后输出符合 ...

  5. intellij idea 中文 汉化包 韩梦飞沙

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 汉化包 百度云盘 下载地址: https://pan.baidu.com/s/1hs6B ...

  6. 51Nod1140 矩阵相乘的结果

    随机化算法. A*B==C那么X*A*B==X*C 降到了n*n复杂度. 多次随机X判断即可. By:大奕哥 #include<bits/stdc++.h> using namespace ...

  7. luoguP3239 [HNOI2015]亚瑟王 概率期望DP

    当初怎么想的来着.....又忘了...... 首先,总期望 = 每张卡片的期望之和 求期望,只要我们求出每张卡片被用掉的概率即可 如果直接上状态$f[i][j]$表示在第$i$轮中,第$j$张牌发动的 ...

  8. Problem F: 深入浅出学算法007-统计求和

    Description 求含有数字a且不能被a整除的4位整数的个数,并求这些整数的和 Input 多组测试数据,先输入整数T表示组数然后每组输入1个整数a(1<=a<=9) Output ...

  9. 【manacher】模板

    考试竟然写错了manacher!太耻辱了!所以赶快又敲了一遍模板!!一定不能错了aaaa #include<iostream> #include<cstdio> #includ ...

  10. 安装与使用adb

    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ...