UUID压缩

关于UUID概念,截取百度百科简单说明一下:

UUID(Universally Unique Identifier)通用唯一识别码,目的是让分布式系统中的所有元素,都能有唯一的辨识信息,可作为数据库id等。由三部分组成:
(1)当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。
(2)时钟序列。
(3)全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。
UUID的唯一缺陷在于生成的结果串会比较长。

wiki上对UUID的定义:

A universally unique identifier (UUID) is a 128-bit number used to identify information in computer systems.
一个普遍唯一的标识符(UUID)是一个128位的数字。

这里的128位意为:由一组32位数的16进制数字所构成,而一个16进制数可以用4位来表示,故32*4=128。我们用JDK中的UUID工具类取得一个UUID

UUID uu=UUID.randomUUID();
System.out.println(uu.toString());

输出
e1214bfc-bc36-494a-8541-697355796bca

由五部分组成,用-进行连接。总共为36个字符,占用2byte*36个字节,但是通常情况下,我们并不需要-符号,而是需要e1214bfcbc36494a8541697355796bca这样的字符串,所以我们先去除不必要字符,进行第一步压缩:

String uuid = UUID.randomUUID().toString().replaceAll("-","");  
System.out.println(uuid);  

上面提到,uuid是用32个16进制数字组成,每个16进制可用4bit来表示,总共是128bit。那么我们就会想到,如果用64进制数字来表示,每个数字用6bit来表示,那么uuid的长度就变短了。大致思路:128/6=21余2,剩下的2位也记为一位64进制数,那么总共就是22个64进制数,相比较16进制,压缩了1/3。Java代码实现:

//我们先定义64进制由哪些字符表示
private static final char[] _UUID64 = 
    "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".toCharArray();
/**
     * @return java.lang.String
     * @Description 用64进制来表示UUID
     * @Param uu 传入由JDK获得的uuid对象 
     **/
    public static String UUID64(java.util.UUID uu) {
        //用于存放压缩后的uuid值
        char[] uuid64 = new char[22];
        //压缩后数组偏移指针
        int index = 0;
        //获取源uuid的前64位和后64位(返回的是10进制数)
        long most = uu.getMostSignificantBits();
        long least = uu.getLeastSignificantBits();
        //进行与运算(&)的基值,由于我们使用64进制,即可用6bit表示,所以我们取63(111111)来进行切割
        long mask = 63L;

        //将前64位切割10次,还剩余4位参与后64位切割
        for (int off = 58; off >= 4; off -= 6) {
            //截取高位后不要忘记无符号右移回对应位数,因为most和least可能是负数,如果是用>>会可能报数组下标溢出错误。
            long hex = (most & (mask << off)) >>> off;
            //用64进制来表示
            uuid64[index++] = _UUID64[(int) hex];
        }
        //前64位的低4位和后64位的高2位拼接
        int i=(int) (((most & 15) << 2) | ((least & (3 << 62))>>>62));
        uuid64[index++] = _UUID64[i];
        //前64位剩余的62位先分割10次,剩余2位单独处理
        for (int off = 56; off >= 2; off -= 6) {
            long hex = (least & (mask << off)) >>> off;
            uuid64[index++] = _UUID64[(int) hex];
        }
        //处理剩余2位
        uuid64[index] = _UUID64[(int) least & 3];
        //返回字符串
        return uuid64.toString();
    }

加个图帮助理解:
uuid

猜你喜欢

转载自blog.csdn.net/GD_Hacker/article/details/81216169