hadoop源码分析-WritableComparator

本文详细分析了Hadoop中WritableComparator类的compareBytes方法,解释了为何使用b1[i] & 0xff避免负数位扩展的问题。同时,介绍了readInt方法的字节转换逻辑。此外,文章探讨了Hadoop对于long、int的zero-compressed encoded变长编码方式,包括不同数值范围的字节数编码规则,并展示了writeVLong和readVLong方法的实现过程。
摘要由CSDN通过智能技术生成

类:public class WritableComparator implements RawComparator 

方法一:

  public static int compareBytes(byte[] b1, int s1, int l1,
                                 byte[] b2, int s2, int l2) {
    int end1 = s1 + l1;
    int end2 = s2 + l2;
    for (int i = s1, j = s2; i < end1 && j < end2; i++, j++) {
      int a = (b1[i] & 0xff);
      int b = (b2[j] & 0xff);
      if (a != b) {
        return a - b;
      }
    }
    return l1 - l2;
  }

分析:b1[i] & 0xff

Java中的一个byte,其范围是-128~127的,如果不进行&0xff,
那么当一个byte会转换成int时,对于负数,会做位扩展,举例来说,一个byte的-1(即0xff),
会被转换成int的-1(即0xffffffff),那么转化出的结果就不是我们想要的了。
而0xff默认是整形,所以,一个byte跟0xff相与会先将那个byte转化成整形运算,这样,
结果中的高的24个比特就总会被清0,

方法二: 

 public static int readInt(byte[] bytes, int start) {
    return (((bytes[start  ] & 0xff) << 24) +
            ((bytes[start+1] & 0xff) << 16) +
            ((bytes[start+2] & 0xff) <<  8) +
            ((bytes[start+3] & 0xff)));


  }

分析:(bytes[start+2] & 0xff) <<  8)左移8位,右边补8个0,8个0为低位,(bytes[start+3] & 0xff))是8个低位数字,刚好相加


Hadoop对于long、int (化成long进行编码)的编码设计了自己的一套编码方式,这是一个zero-compressed encoded的变长编码方式,有利于大大压缩冗余数据。具体算法其实很简单,具体来说有如下几点:

1、对于-112 <= i <= 127的整数,只用1个字节byte来表示;如果超过上述范围时,编码第一个字节则会用来表示i的总字节数,后面则跟着 i 的字节;

2、如果i大于0,则编码的第一个字节 b 范围在-113和-120之间,则 i 会有 (-112 - b)个字节,所以可以表示有1-8个字节;

3、如果i小于0,则编码第一个字节 b 范围在 -121 和 -128之间,则 i 会有 (-120 - b)个字节,同样也可以表示有1-8个字节。(Hadoop的实现里,当i为负数被编码的是 i 补码)。

方法三:

public static void writeVLong(DataOutput stream, long i) throws IOException {
    if (i >= -112 && i <= 127) {
      stream.writeByte((byte)i);
      return;
    } 
    int len = -112;
    if (i < 0) {
      i ^= -1L; //与或-1    取反
      len = -120;
    }  
    long tmp = i;
    while (tmp != 0) {
      tmp = tmp >> 8; //右移一个字节  len减一到最小为-128
      len--;
    }
    stream.writeByte((byte)len);
    len = (len < -120) ? -(len + 120) : -(len + 112);
    for (int idx = len; idx != 0; idx--) {
      int shiftbits = (idx - 1) * 8;
      long mask = 0xFFL << shiftbits;
      stream.writeByte((byte)((i & mask) >> shiftbits));
    }
  }


  public static long readVLong(byte[] bytes, int start) throws IOException {
    int len = bytes[start];
    if (len >= -112) {
      return len;
    }
    boolean isNegative = (len < -120);
    len = isNegative ? -(len + 120) : -(len + 112);
    if (start+1+len>bytes.length)
      throw new IOException( "Not enough number of bytes for a zero-compressed integer");
    long i = 0;
    for (int idx = 0; idx < len; idx++) {
      i = i << 8; //读一次为一个字节,满一字节左移8位
      i = i | (bytes[start+1+idx] & 0xFF);
    }
    return (isNegative ? (i ^ -1L) : i);
  }




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值