背景
标准 UUID 虽然唯一性有保证,但长达 36 位的字符串在某些场景下显得过于冗长。比如作为 URL 短链的原始 ID,或者作为 Redis 缓存的 Key,缩短长度能提升可读性和存储效率。
这里分享一种基于 Java 原生库的轻量级方案,将 UUID 压缩为 8 位字符,同时尽量保持分布均匀。
核心思路
标准 UUID 是 128 位,通常表示为 32 个十六进制字符。我们的目标是将这 32 个字符映射到更短的集合中。具体做法是:
- 去掉 UUID 中的横杠,得到纯十六进制字符串。
- 每 4 个字符一组,共 8 组。
- 将每组 4 位十六进制数转为十进制整数。
- 对 62 取模(对应 26 小写字母 + 26 大写字母 + 10 数字)。
- 查表获取对应的字符。
这样得到的 8 位字符串,理论上组合空间为 $62^8$,约为 218 万亿种可能,对于大多数业务场景足够使用。
代码实现
下面是具体的 Java 实现,注意使用了 StringBuilder 替代旧版的 StringBuffer 以提升性能:
package test;
import java.util.UUID;
public class Test {
// 定义字符集:a-z, 0-9, A-Z
public static String[] chars = new String[] {
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
};
public static String generateShortUuid() {
StringBuilder shortBuffer = new StringBuilder();
// 获取标准 UUID 并移除横杠
String uuid = UUID.randomUUID().toString().replace("-", "");
// 每 4 位十六进制转一个字符
for (int i = 0; i < 8; i++) {
String str = uuid.substring(i * 4, i * 4 + 4);
int x = Integer.parseInt(str, 16);
// 62 进制映射
shortBuffer.append(chars[x % 0x3E]);
}
return shortBuffer.toString();
}
public static void main(String[] args) {
for(int i = 0; i < 1000; i++){
System.out.println(generateShortUuid())
}
}

