• hadoop 中对Vlong 和 Vint的压缩方法


    hadoop 中对java的基本类型进行了writeable的封装,并且所有这些writeable都是继承自WritableComparable的,都是可比较的;并且,它们都有对应的get() 和 set()方法,

    其中对整型(int 和 long)进行编码的时候,有固定长度格式(intWritable和LongWritable)和可变长度格式(VIntWritable 和 VLongWritable),其中VIntWritable和VLongWritable的编码规则是一样的,

    所以VIntWritable的输出可以用VLongWritable读入。其实在VIntWritable的write(DataOUtput out) 与 readFields(DataInput in)中分别调用的是WritableUtils.writeVint(out)和WritableUtils.readVint(int),

    而writeVint()和readVint()方法也只是简单的调用了writeVLong和readVLong方法。通过writeVInt()写入的数据自然可以通过readVLong()来进行读人;编码规则如下:

    其基本思想  主要思想是大的负数的压缩 ,先反码操作,将负数取反,负数一旦取反,前面的字节就有可能变零了。 然后没八位一组截取成 一个字节

     

    写入

    1. public static void writeVLong(DataOutput stream, long i) throws IOException {  
    2. // 如果在一个字节可以表示的范围内 直接返回   
    3.  if (i >= -112 && i <= 127) {  
    4.      stream.writeByte((byte)i);  
    5.      return;  
    6.    }  
    7.     //把负数变成正数   
    8.    int len = -112;  
    9.    if (i < 0) {  
    10.      i ^= -1L; // take one's complement'  
    11.      len = -120;  
    12.    }  
    13.        
    14.   //判断正数有几个位数 通过右移实现  
    15.    long tmp = i;  
    16.    while (tmp != 0) {  
    17.      tmp = tmp >> 8;  
    18.      len--;  
    19.    }  
    20.        
    21.    // 写入第一个字节 该字节标识 这个数十正数还是负数 以及接下来有几个字节属于这个数   
    22.    stream.writeByte((byte)len);  
    23.        
    24.    // 判断需要几个字节表示该数  
    25.    len = (len < -120) ? -(len + 120) : -(len + 112);  
    26.        
    27. //以每八位一组截取 成一个字节   
    28.   
    29.    for (int idx = len; idx != 0; idx--) {  
    30.      int shiftbits = (idx - 1) * 8;  
    31.      long mask = 0xFFL << shiftbits;  
    32.      stream.writeByte((byte)((i & mask) >> shiftbits));  
    33.    }  
    34.  }  

    读取

    1. public static long readVLong(byte[] bytes, int start) throws IOException {  
    2.     int len = bytes[start];  
    3.     if (len >= -112) {  
    4.       return len;           
    5.     }  
    6.     boolean isNegative = (len < -120);     
    7.     len = isNegative ? -(len + 120) : -(len + 112);     
    8.     if (start+1+len>bytes.length)      
    9.       throw new IOException(  
    10.                             "Not enough number of bytes for a zero-compressed integer");  
    11.     long i = 0;  
    12.     for (int idx = 0; idx < len; idx++) {    
    13.       i = i << 8;  
    14.       i = i | (bytes[start+1+idx] & 0xFF);  
    15.     }  
    16.     return (isNegative ? (i ^ -1L) : i);      
    17.   }  
  • 相关阅读:
    正则表达式
    跨域请求/SpringMVC拦截器
    批量导出
    什么是2MSL以及TIME_WAIT的作用
    使用jstack精确找到异常代码的
    nettry 入站事件如何传递到下一个handler
    netty 引用计数器 ,垃圾回收
    elasticsearch 查询优化
    Spark性能优化指南-高级篇(spark shuffle)
    Broadcast与map进行join,避免shuffle,从而优化spark
  • 原文地址:https://www.cnblogs.com/yuhan-TB/p/3742625.html
Copyright © 2020-2023  润新知