hadoop中实现定制Writable类
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);}?
轉載于:https://www.cnblogs.com/wuyudong/p/4332080.html
總結
以上是生活随笔為你收集整理的hadoop中实现定制Writable类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 简单仿百度自动搜索框
- 下一篇: HDFS相关概念