java中UUID的toString方法,生成的uuid是36位了,在项目中,有时候会显的过长,占用空间比较多,如何能够压缩存储下,又能够保证uuid的唯一性呢?
一、 思路
看源码后,发现UUID的格式是这样的:
<time_low> "-" <time_mid> "-" <time_high_and_version> "-" <variant_and_sequence> "-" <node></>
它是一堆-
分割的16进制的数字,如果只是为了保证唯一性,那这些-
对我们来说是没有实际的用处的,可以直接去掉,这样我们就节省了4个字节,剩下32个字节。
接下来再想办法继续压缩这32个字节。
16进制的字符一共有16个,等于2的4次方。如果我们去自己对这16个字符进行编码,只需要4个bit就可以表示这16个字符,从0000 - 1111一共16个。
一个byte有8个bit,所以一个字节的高4位和低4位一共能放两个字符编码。
这样我们就能够再节省一半的空间。
最终我们就能够以16个字节存储36个字节的uuid了,空间节省了一半多。
二、 代码编写
private static String compressUUID(UUID uuid) {
StringBuilder resultBuilder = new StringBuilder();
String uuidStr = uuid.toString();
boolean isFirst = false;
int tmp = 0;
for (int i = 0; i < 36; i++) {
if (i == 8 || i == 13 || i == 18 || i == 23) {
continue;
}
char c = uuidStr.charAt(i);
short shortValue = Short.valueOf(String.valueOf(c), 16);
if (!isFirst) {
tmp += shortValue;
isFirst = true;
} else {
tmp = tmp << 4;
tmp += shortValue;
resultBuilder.append((char) tmp);
tmp = 0;
isFirst = false;
}
}
return resultBuilder.toString();
}
代码相对比较简单。
for循环一遍,如果遇到-
则跳过。
然后把char转换成short,把第一个字符放到short的高四位,把第二个字符放在short的低四位,然后把这个short转成char。
最后拼接成一个字符串。
三、 问题
这样压缩后,能够在代码中正常使用,但是对人来说可读性太差了,如果你打印的话,可能还显示不出来,这一点不是特别好。
大家看还有没有更好的解决方法,一起来讨论下。