通常我們生成的uuid都是128位,以36/32位十六進制表示纵竖。長度過長肩杈,但真正要壓縮它的原因是由于我方平臺需要與對方平臺傳遞這個uuid,二對方平臺支持的最大長度是30位堪伍。
ps 若是用作數(shù)據(jù)庫主鍵的話還是比較推薦Twitter的SnowFlake算法锚烦,長度才64位,比uuid短了一半杠娱;
壓縮原理:使用base64將原來4位編碼為1字符的方式變?yōu)?位為一字符挽牢,將原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)
方法參數(shù)只能是以-
分割的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);
}