UUID压缩

通常我们生成的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);
}

你可能感兴趣的:(UUID压缩)