240

如果我使用Long uuid = UUID.randomUUID().getMostSignificantBits()它发生碰撞的可能性有多大。它切断了最低有效位,因此您可能会遇到碰撞,对吗?

4

5 回答 5

219

根据文档,静态方法UUID.randomUUID()生成类型 4 UUID。

这意味着 6 位用于某些类型信息,其余 122 位是随机分配的。

六个非随机位分布在 UUID 的最高有效一半中,四个在最低有效一半中。因此,您的 UUID 的最重要的一半包含 60 位随机性,这意味着您平均需要生成 2^30 个 UUID 才能发生冲突(相比之下,完整 UUID 需要 2^61 个)。

所以我会说你是相当安全的。但是请注意,正如 Carl Seleborg 所提到的,对于其他类型的 UUID,这绝对不是真的。

顺便说一句,使用 UUID 的最低有效一半(或仅使用 SecureRandom 生成随机长整数)会稍微好一些。

于 2008-11-28T10:37:27.957 回答
57

Raymond Chen 对此有一篇非常出色的博文:

GUID 是全局唯一的,但 GUID 的子字符串不是

于 2008-11-28T10:26:44.343 回答
13

我认为这是使用 randomUUID 的最佳示例:

http://www.javapractices.com/topic/TopicAction.do?Id=56

于 2012-05-15T10:02:29.447 回答
10

你最好只生成一个随机长值,然后所有位都是随机的。在 Java 6 中, new Random() 使用 System.nanoTime() 加上一个计数器作为种子。

有不同程度的独特性。

如果您需要跨多台机器的唯一性,您可以拥有一个中央数据库表来分配唯一 ID,甚至是批量唯一 ID。

如果您只需要在一个应用程序中具有唯一性,则可以只使用一个计数器(或根据您的要求从 currentTimeMillis()*1000 或 nanoTime() 开始的计数器)

于 2009-03-13T21:36:17.507 回答
7

使用时间YYYYDDDD(年份 + 年份)作为前缀。这减少了表和索引中的数据库碎片。此方法返回byte[40]. 我在混合环境中使用它,其中 Active Directory SID ( varbinary(85)) 是 LDAP 用户的键,应用程序自动生成的 ID 用于非 LDAP 用户。此外,交易表(银行业)中每天的大量交易不能使用标准Int类型的键

private static final DecimalFormat timeFormat4 = new DecimalFormat("0000;0000");

public static byte[] getSidWithCalendar() {
    Calendar cal = Calendar.getInstance();
    String val = String.valueOf(cal.get(Calendar.YEAR));
    val += timeFormat4.format(cal.get(Calendar.DAY_OF_YEAR));
    val += UUID.randomUUID().toString().replaceAll("-", "");
    return val.getBytes();
}
于 2013-05-03T00:31:13.270 回答