MapReduce Key排序原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/c13232906050/article/details/65441205

如何写一个属于自己的数据类型(Writable)

疑问一

IntWritable, LongWritable, Text和Java的int, long, String有什么区别?

答:数据在集群中传输时,xxWritable转化成字节流(byte[])进行传输,具体方法为接口Writable的write(DataOutput out);解析还原时,使用接口Writable的readFields(DataInput in)进行还原;排序比较时,使用接口Comparable的compareTo方法进行比较。

写属于自己的IntWritable

PS:以下代码参照IntWritable源码

public class MyInt implements WritableComparable<MyInt> {
    // 就是对这个value的封装
    private int value;

    // 构造方法
    public MyInt() {}
    public MyInt(int i) { this.value = i; }

    // getter and setter
    public int get() { return this.value; }
    public void set(int i) { this.value = i; }

/
*******************************************************/
/* readFields和write可以自己自定义,只要能正确还原value即可 */
/*******************************************************/
    // 解析字节流,即还原数据
    @Override
    public void readFields(DataInput in) throws IOException {
        this.value = in.readInt();
    }
    // 把value转化成字节流
    @Override
    public void write(DataOutput out) throws IOException {
        out.writeInt(this.value);
    } 

/*******************************************************/
/* 修改compareTo方法即可自定义MyInt类型的排序方式           */
/*******************************************************/
    @Override
    public int compareTo(MyInt o) {
        // 按照从小到大排序
        if (this.value != o.value) {
            return this.value < o.value ? -1 : 1;
        } else {
            return 0;
        }
    }

/*******************************************************/
/* equals, hashCode, toString可选,最好实现。            */
/*******************************************************/
    @Override
    public int hashCode() {
        return this.value;
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof MyInt)) {
            return false;
        }
        return ((MyInt) o).value == this.value;
    }

    @Override
    public String toString() {
        return Integer.toString(this.value);
    }
}

/*******************************************************/
/* 不使用MyInt重写的compareTo方法,                       */
/* 而使用下面注册的WritableComparator的compare方法。       */
/* 下面一部分讲如何写WritableComparator类。                     */
/* 注意:下面的代码不能写在MyInt类外,会不起作用。            */
/*******************************************************/
    static {
        WritableComparator.define(MyInt.class, new IntComparator());
    }

疑问二

如果不想自己写Writable,就想用现成提供的(用IntWritable举例),但是IntWritable默认的是从小到大的排序,我想从大到小或者第一位先排序再按大小排序等等(后者排序为:1,11,123,2,21,231)。该如何操作?

答:和Java原生的Comparator接口类似,Hadoop用的是RawComparator(也是继承Comparator),默认实现类是:WritableComparator。

所以,实现RawComparator接口或者继承WritableComparator即可。

通常使用继承WritableComparator的方式,因为RawComparator是对字节流的比较,需要熟悉了解字节流的比较方法;而WritableComparator内涵许多对字节流的处理方法,可以用于转化字节流。

写属于自己的IntComparator

下面使用继承WritableComparator的方式来写自己的IntComparator。
(实现RawComparator的方式参考WritableComparator的内部实现)


/**
 * WritableComparator主要用来比较的方法有三个:
 * 方法1,compare(byte[],int,int,byte[],int,int);
 * 方法2,compare(WritableComparable,WritableComparable);
 * 方法3,compare(Object,Object);
 * 
 * 关系:
 *     1,方法3实际调用方法2,所以方法2和方法3其实一样;
 *     2,方法1的逻辑是把字节流转化成指定的Writable,这里是MyInt.class
 *     3,实际使用中,只会调用方法1,而方法1还原后,调用方法2。
 *     
 */
public class IntComparator extends WritableComparator {
    /**
     * 最后一个参数必须是true,参数名为:createInstances,
     * 意思是:是否创建方法1中用到的还原目标对象实例。
     * 这里不重写方法1,所以必须为true;默认为false,重写方法1则可以为false。
     */
    public IntComparator() {
        super(MyInt.class, true);
    }

    @Override
    public int compare(WritableComparable a, WritableComparable b) {
        int thisValue = ((MyInt) a).get();
        int thatValue = ((MyInt) b).get();
        // 从大到小
        if (thisValue != thatValue) {
            return thisValue > thatValue ? -1 : 1;
        } else {
            return 0;
        }
    }
}

写完WritableComparator后,需要在Job配置一下

someMethod() {
    Job job = Job.getInstance();

    (省略一些代码)

    job.setSortComparatorClass(IntComparator.class);

    (省略一些代码)
}

key排序优先级

三种key排序方法,优先级从高到低:

  1. Job.setSortComparatorClass();
  2. WritableComparator.define();
  3. Comparable中的compareTo();

猜你喜欢

转载自blog.csdn.net/c13232906050/article/details/65441205