Java中UUID默认不是32位字符串,而是36位含4个短横线的字符串;去掉横线后为32位十六进制字符,可用toString().replace("-", "")或String.format("%016x%016x", most, least)高效获取。

Java里UUID默认是32位十六进制字符串吗?
不是。UUID.toString() 返回的是 36 位字符串(如 "f47ac10b-58cc-4372-a567-0e02b2c3d479"),含 4 个短横线。所谓“32位不重复唯一主键”,实际是指去掉分隔符后的纯十六进制字符,共 32 位。
怎么从UUID得到32位无横线字符串
最直接的方式是调用 toString() 后用 replace("-", "") 去掉横线。但要注意:这不是“生成”新UUID,而是格式转换。
-
UUID.randomUUID().toString().replace("-", "")是最常用写法,结果是"f47ac10b58cc4372a5670e02b2c3d479" - 别用
replaceAll("\-", "")—— 正则开销没必要,replace()是字面量替换,更快更安全 - 如果高并发下频繁调用,建议复用
StringBuilder或直接操作long值(见下一点)
想绕过String拼接,直接拼出32位十六进制?
可以。UUID内部是两个 long,用 String.format() 或位运算转16进制更高效,避免中间 String 对象:
UUID id = UUID.randomUUID();
String s = String.format("%016x%016x", id.getMostSignificantBits(), id.getLeastSignificantBits());
这个 s 就是严格 32 位小写十六进制字符串。注意:%016x 确保高位补零,否则可能不足16位导致总长不到32。
立即学习“Java免费学习笔记(深入)”;
- 大小写敏感场景(比如MySQL列设为
BINARY)要统一,推荐小写,%016x默认小写 - 不要用
toUpperCase()后再截取——多一次拷贝,且破坏不可变性 - JDK 17+ 可考虑
HexFormat.of().toHexDigits(...),但目前兼容性不如String.format
32位UUID当主键真能保证不重复?
概率上极低,但不是数学意义上“绝对不重复”。UUID.randomUUID() 是基于时间戳 + 随机数 + MAC地址(或伪随机 fallback)的 version 4,碰撞概率约为 2^(-122)。
- 单机每秒生成 1 万个,持续 100 年,碰撞期望值仍远小于 1
- 真正风险点不在 UUID 本身,而在你用错方式:比如用
new Random()自己造、或用系统毫秒时间戳简单拼接 - 如果业务要求强一致性(如金融幂等ID),别只靠 UUID —— 加上服务实例标识、序列号或数据库自增辅助校验
- MySQL 中存为
CHAR(32)比VARCHAR(32)略快(定长),但索引效率差异微乎其微;别存成TEXT
真正容易被忽略的是:UUID 作为主键会导致二级索引变大、插入时页分裂加剧,尤其在 InnoDB 中。如果只是需要“业务侧不重复”,考虑 Snowflake 或数据库序列更合适。










