温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Hadoop中如何自定义类型

发布时间:2021-07-29 15:43:54 来源:亿速云 阅读:111 作者:Leah 栏目:云计算

这期内容当中小编将会给大家带来有关Hadoop中如何自定义类型,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

代码如下。

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

规定了对象内部比较的方法

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

定义外部比较器的基本方法,其中equals是用来确定两个比较器是否相等

关于对象内部比较和外部比较这两个接口的区别和使用场景如下:

个人总结:

Comparable是对象内部固有的比较,一个类的不同对象肯定需要很自然的比较,无论使用在任何地方 Comparator是外部比较,在不改变对象内部固有的比较标准的前提下,增加新的比较行为, 尤其是对已有的类型,String,Integer等,如果我们想要不同的比较行为,例如绝对值比较,那么我们不能修改这写类固有的比较标准,而是加入自定义的外部比较器, 在外部比较器中定义新的比较规则,同时在需要比较的地方,插入我们自定义的外部比较器实例

我们知道hadoop中有自定义类型,需要实现, WritableComparable接口,而WritableComparable接口继承之一便是Comparable接口。

因此,自定义的类型需要实现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并没有直接使用这个基于对象内部比较机制,对需要排序比较的地方进行key的排序,而是借助外部比较器,统一介入的。 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调用,获得当前类型对应的外部比较器实例。WritableComparator内部有缓存,其中会缓存类型和其对应的外部比较器。get方法会从缓存中取得类型对应的外部比较器,如果取得为空,则手动生成一个外部比较器,

外部比较器,默认的比较方法是按照对象的内部比较标准进行的。

@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
  }

而这个方法默认也是使用对象内部比较的标准。

在考虑性能的时候,需要将这个方法的默认行为改成基于bytes字节的比较,那么就需要用户自己写一个外部比较类的子类,并手动放到WritableComparator类中的内部缓存。

这种手动放入到缓存的过程,在自定义类型中完成,(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());
 }

这样,就改变了外部比较器默认的比较标准,按照用户自定义的compare方法进行比较。

那么,什么时候要自定义外部比较器呢?

1)效率考虑,如上所述 2)排序的规则发生变化,所有需要排序的地方,可以指定外部比较器,让其发生比较规则的改变(默认的比较都是自定义类型中的外部比较器比较规则)

比如,二次排序等。

上述就是小编为大家分享的Hadoop中如何自定义类型了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI