通常我们生成的uuid都是128位,以36/32位十六进制表示。长度过长,但真正要压缩它的原因是由于我方平台需要与对方平台传递这个uuid,二对方平台支持的最大长度是30位。
ps 若是用作数据库主键的话还是比较推荐Twitter的SnowFlake算法,长度才64位,比uuid短了一半;
压缩原理:使用base64将原来4位编码为1字符的方式变为6位为一字符,将原uuid的分隔符 -
去掉,使用无填充的base64可编码为22字符长度;
public class UUIDUtil {
/**
* 压缩
* @param src uuid字符串,可带有{@code -}
* @return base64字符串,length=22
*/
public static String compress(String src) {
UUID uuid = UUID.fromString(src);
long msb = uuid.getMostSignificantBits();
long lsb = uuid.getLeastSignificantBits();
byte[] b = new byte[16];
for (int i = 0; i < 8; i++) {
b[i] = (byte) (msb >>> (8 * (7-i)) & 0xff);
b[i+8] = (byte) (lsb >>> (8 * (7-i)) & 0xff);
}
return Base64.getEncoder().withoutPadding().encodeToString(b);
}
/**
* 解压
* @param src base64字符串,length=22
* @return uuid字符串,{@code -}分割
*/
public static String decompress(String src) {
byte[] b = Base64.getDecoder().decode(src);
long msb = 0;
long lsb = 0;
for (int i=0; i<8; i++) {
msb = (msb << 8) | (b[i] & 0xff);
lsb = (lsb << 8) | (b[i+8] & 0xff);
}
return new UUID(msb, lsb).toString();
}
UUID中,使用两个long类型变量mostSigBits(msb)、leastSigBits(lsb)分别表示高64位与低64位;以上代码中compress(String src)
方法参数只能是以-
分割的36位uuid,若要兼容32位uuid,将该方法该为一下代码。原理可参见UUID.fromString(String name)
方法;
/**
* 压缩
* @param src uuid字符串,可带有{@code -}
* @return base64字符串,length=22
*/
public static String compress(String src) {
String[] components = src.split("-");
if (components.length != 5) {
components = new String[5];
src = src.replace("-", "");
components[0] = src.substring(0, 8);
components[1] = src.substring(8, 12);
components[2] = src.substring(12, 16);
components[3] = src.substring(16, 20);
components[4] = src.substring(20, 32);
}
for (int i=0; i<5; i++)
components[i] = "0x"+components[i];
long msb = Long.decode(components[0]).longValue();
msb <<= 16;
msb |= Long.decode(components[1]).longValue();
msb <<= 16;
msb |= Long.decode(components[2]).longValue();
long lsb = Long.decode(components[3]).longValue();
lsb <<= 48;
lsb |= Long.decode(components[4]).longValue();
byte[] b = new byte[16];
for (int i = 0; i < 8; i++) {
b[i] = (byte) (msb >>> (8 * (7-i)) & 0xff);
b[i+8] = (byte) (lsb >>> (8 * (7-i)) & 0xff);
}
return Base64.getEncoder().withoutPadding().encodeToString(b);
}
网友评论