溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Hadoop中如何自定義類型

發(fā)布時間:2021-07-29 15:43:54 來源:億速云 閱讀:116 作者:Leah 欄目:云計算

這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)Hadoop中如何自定義類型,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

代碼如下。

public interface Comparable<T> {
    public int compareTo(T o);
}

規(guī)定了對象內(nèi)部比較的方法

public interface Comparator<T> {
     int compare(T o1, T o2);
     boolean equals(Object obj);
}

定義外部比較器的基本方法,其中equals是用來確定兩個比較器是否相等

關(guān)于對象內(nèi)部比較和外部比較這兩個接口的區(qū)別和使用場景如下:

個人總結(jié):

Comparable是對象內(nèi)部固有的比較,一個類的不同對象肯定需要很自然的比較,無論使用在任何地方 Comparator是外部比較,在不改變對象內(nèi)部固有的比較標(biāo)準(zhǔn)的前提下,增加新的比較行為, 尤其是對已有的類型,String,Integer等,如果我們想要不同的比較行為,例如絕對值比較,那么我們不能修改這寫類固有的比較標(biāo)準(zhǔn),而是加入自定義的外部比較器, 在外部比較器中定義新的比較規(guī)則,同時在需要比較的地方,插入我們自定義的外部比較器實例。

我們知道hadoop中有自定義類型,需要實現(xiàn), WritableComparable接口,而WritableComparable接口繼承之一便是Comparable接口。

因此,自定義的類型需要實現(xiàn)compareTo方法

如,LongWrite.class

@Override
  public int compareTo(LongWritable o) {
    long thisValue = this.value;
    long thatValue = o.value;
    return (thisValue<thatValue ? -1 : (thisValue==thatValue ? 0 : 1));
  }

但是hadoop并沒有直接使用這個基于對象內(nèi)部比較機制,對需要排序比較的地方進(jìn)行key的排序,而是借助外部比較器,統(tǒng)一介入的。 hadoop中的外部比較器, WritableComparator。

public static WritableComparator get(
      Class<? extends WritableComparable> c, Configuration conf) {
    WritableComparator comparator = comparators.get(c);
    if (comparator == null) {
      // force the static initializers to run
      forceInit(c);
      // look to see if it is defined now
      comparator = comparators.get(c);
      // if not, use the generic one
      if (comparator == null) {
        comparator = new WritableComparator(c, conf, true);
      }
    }
    // Newly passed Configuration objects should be used.
    ReflectionUtils.setConf(comparator, conf);
    return comparator;
  }

該方法會被Job調(diào)用,獲得當(dāng)前類型對應(yīng)的外部比較器實例。WritableComparator內(nèi)部有緩存,其中會緩存類型和其對應(yīng)的外部比較器。get方法會從緩存中取得類型對應(yīng)的外部比較器,如果取得為空,則手動生成一個外部比較器,

外部比較器,默認(rèn)的比較方法是按照對象的內(nèi)部比較標(biāo)準(zhǔn)進(jìn)行的。

@SuppressWarnings("unchecked")
  public int compare(WritableComparable a, WritableComparable b) {
    return a.compareTo(b);
  }

  @Override
  public int compare(Object a, Object b) {
    return compare((WritableComparable)a, (WritableComparable)b);
  }

但是,hadoop在使用這個外部比較器的地方的,使用方式是:(例如,MapOutputBuffer,map端spill)

public int compare(final int mi, final int mj) {
      final int kvi = offsetFor(mi % maxRec);
      final int kvj = offsetFor(mj % maxRec);
      final int kvip = kvmeta.get(kvi + PARTITION);
      final int kvjp = kvmeta.get(kvj + PARTITION);
      // sort by partition
      if (kvip != kvjp) {
        return kvip - kvjp;
      }
      // sort by key
      return comparator.compare(kvbuffer,
          kvmeta.get(kvi + KEYSTART),
          kvmeta.get(kvi + VALSTART) - kvmeta.get(kvi + KEYSTART),
          kvbuffer,
          kvmeta.get(kvj + KEYSTART),
          kvmeta.get(kvj + VALSTART) - kvmeta.get(kvj + KEYSTART));
    }

使用的是外部比較器的這個方法,如下

@Override
  public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
    try {
      buffer.reset(b1, s1, l1);                   // parse key1
      key1.readFields(buffer);
      
      buffer.reset(b2, s2, l2);                   // parse key2
      key2.readFields(buffer);
      
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    
    return compare(key1, key2);                   // compare them
  }

而這個方法默認(rèn)也是使用對象內(nèi)部比較的標(biāo)準(zhǔn)。

在考慮性能的時候,需要將這個方法的默認(rèn)行為改成基于bytes字節(jié)的比較,那么就需要用戶自己寫一個外部比較類的子類,并手動放到WritableComparator類中的內(nèi)部緩存。

這種手動放入到緩存的過程,在自定義類型中完成,(LongWritable為例) (1)自定義外部比較器的子類。

public static class Comparator extends WritableComparator {
    public Comparator() {
      super(LongWritable.class);
    }

    @Override
    public int compare(byte[] b1, int s1, int l1,
                       byte[] b2, int s2, int l2) {
      long thisValue = readLong(b1, s1);
      long thatValue = readLong(b2, s2);
      return (thisValue<thatValue ? -1 : (thisValue==thatValue ? 0 : 1));
    }
  }

(2)手動注入到緩存中

static {                                       
    // register default comparator
    WritableComparator.define(LongWritable.class, new Comparator());
 }

這樣,就改變了外部比較器默認(rèn)的比較標(biāo)準(zhǔn),按照用戶自定義的compare方法進(jìn)行比較。

那么,什么時候要自定義外部比較器呢?

1)效率考慮,如上所述 2)排序的規(guī)則發(fā)生變化,所有需要排序的地方,可以指定外部比較器,讓其發(fā)生比較規(guī)則的改變(默認(rèn)的比較都是自定義類型中的外部比較器比較規(guī)則)

比如,二次排序等。

上述就是小編為大家分享的Hadoop中如何自定義類型了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI