将UUID转换为唯一的整数ID?

76

我想知道将UUID转换为唯一整数的最简单方法是什么?我尝试使用哈希码,但有人告诉我如果使用哈希码它并不总是唯一的。

那么最简单的方法是什么呢?哈希码是否唯一?


2
不,根据定义它不是独一无二的。而且,如果它是独一无二的,那么为什么还需要UUID呢? - Ingo
定义唯一。是全局的,还是仅在您的应用程序或代码中? - Bart van Heukelom
只是由于某个愚蠢的规范,我需要一个应用程序唯一整数,我想利用UUID类,但事实证明我无法缩小它。 - Alex Hope O'Connor
4
如果你问出真正的问题:如何获得一个应用程序唯一的整数?我能否将UUID转换为它?那么我们可以回答你的问题,而不仅是告诉你不能将UUID用于该目的...... - pgras
6个回答

47

由于UUID是128位,而int只有32位,因此您将遇到问题。 您只能接受冲突的风险并尝试将其强行缩小到较小的空间(hashCode可能是一种不错的方法),或者找到其他替代方案(直接使用UUID,映射到BigInteger - 在不知道原因的情况下很难判断)。


18

如何创建一个应用程序唯一的整数?

如果需要即使在重启后或应用程序被聚集的情况下仍保持唯一,可以使用数据库序列。

如果只需要在运行时保持唯一,可以使用静态的AtomicInteger

编辑(添加示例):

public class Sequence {

  private static final AtomicInteger counter = new AtomicInteger();

  public static int nextValue() {
    return counter.getAndIncrement();
  }
}

用法:

int nextValue = Sequence.nextValue();

这是线程安全的(不同的线程将始终接收到不同的值,并且不会丢失任何值)


你能给我一个使用AtomicInteger的例子吗? - Alex Hope O'Connor
1
使用应进行编辑;显示“Counter.nextValue();”,但类名为“Sequence”。 - Thomas Sunderland
这个选项只能被单个JVM使用,集群(多个JVM)无法使用此选项。 - Eric Wei
如果生成的不同值超出了int范围,会发生什么?这种情况可能发生吗? - Coder17
@Coder17 你会得到一个整数/数字溢出异常。但是你最终会得到20亿次调用吗? - TheRealChx101

8
UUID是一个16字节的数字(128位)。你不能将它压缩成一个int(32位),同时保持其唯一性。
从数学上讲:2的96次方个UUID将共享相同的Java-int大小哈希值(这非常多)。
有一种解决方法-某些真实的UUID通常具有相当静态的部分。因此,在孤立的情况下,UUID的真正唯一部分可能不到32位。

6
我们有一个要求,需要将所有的UUID转换为序列号。最终,我们测试并使用了以下算法:
  1. 使用ECMA多项式0xC96C5795D7870F42获取uuid(16字节)的CRC64。不要使用ISO多项式,因为它可能会导致某些UUID生成算法发生大量冲突。
  2. 现在我们有crc64(8字节)。取前N个字节(在我们的情况下是5个,在您的情况下是4个字节为int和所有字节为int64)
我们测试了这种方法,并且对于数百万个UUID有效。
我们的额外步骤:将5字节数字转换为基数36的数字,最后我们得到SN:4YD3SOJB。

很好!但是有没有使用特定多项式的CRC64库?我正在使用Python,有一个叫做CRC64ISO的库,但我猜这不是你指的。即使是C库也可以,因为我可以使用ffi进行调用。 - Kamyar

3
不,哈希码不是(也不能是)唯一的。GUID/UUID的问题在于你需要所有128位来保证唯一性,因此以任何方式缩小它都会出现问题,参见例如GUIDs are globally unique, but substrings of GUIDs aren't
老实说,我认为最好只使用连续的整数,完全跳过GUID这个东西。如果你因为某种原因需要GUID,请直接使用它们,不要尝试从中生成整数。

6
注释: 1)哈希码可能是唯一的,但你不确定。虽然不要依赖它。 2)您不能保证 UUID 的唯一性。只有极低的可能发生冲突。 3)即使您“以任何方式缩小规模”,也不一定会创建任何问题。是的,您增加了碰撞的风险,并且需要注意违反 UUID 标准的后果,但在某些情况下,这可能完全没有问题。 4)该链接已失效。 - Zero3

-3

您可以将uuid转换为BigInteger并保持其唯一性。

              BigInteger  big = new BigInteger(uuid, 16);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接