我需要在Java中创建一个64位的唯一的整数,这样的碰撞几率低。该系统是不是分布式的,所以不同的计算机之间的碰撞是没有问题的。
有什么办法,我们可以在Java中创建一个64位整数,它始终是唯一的?
截至目前我使用 -
long number = System.nanoTime();
这是产生64位唯一的整数正确的方式在Java或者是还有什么我能试试吗?
更新: -
如何做这个呢?这会不会是唯一的?
UUID number = UUID.randomUUID();
long uniqueNumber = number.timestamp();
如果您需要的号码是唯一的一个过程,重新启动之间强大的,你可以使用一个简单的AtomicLong和计时器。
private static final AtomicLong TS = new AtomicLong();
public static long getUniqueTimestamp() {
long micros = System.currentTimeMillis() * 1000;
for ( ; ; ) {
long value = TS.get();
if (micros <= value)
micros = value + 1;
if (TS.compareAndSet(value, micros))
return micros;
}
}
这会给你一个独特的“时间戳”以毫秒精度,但只能处理每毫秒1000个IDS没有走在前面的实际时间。这工作正常,在重新启动的时候会跳过去之前的值(再次假设你有每秒平均不到一百万)
使用HashSet,以确保您存储值的唯一性。然后,您可以检查是否插入是通过检查add返回什么成功。如果值必须是“随机”你可以使用自己的算法,入住或退房手续SecureRandom。
Long getUniqueNumber(HashSet uniqueNumberSet) {
Long unique = generateUniqueNumber();
if(!uniqueNumberSet.add(unique)) { // handle collision }
return unique;
}
作为Marc B
说,最好的办法是简单long
它初始化为零,每递增你需要一个新的价值的时间。
如果你需要的并发,或如果性能是不是一个问题的话,那么你可以使用AtomicLong
通过Loc Ha
的建议;但是,如果你真的需要它是一个长期的,而不是一个int,那么我怀疑你将要产生大量的人,所以你应该避免AtomicLong
的额外开销,除非你确信你还需要并发。
System.nanoTime()
是不是一个好主意,因为你不能保证它连续两次调用总是产生不同的值。
编辑(覆盖问题更新)
不,UUID的时间戳部分是不能保证是唯一的,正是相同的原因,System.nanoTime()不能保证是唯一的。如果UUID的时间戳是独一无二的,那么就没有必要有一个UUID类型,我们只是始终使用时间戳的一部分。时间总是一个坏的方式去保证唯一性。
你想获得唯一的ID,用适当的方式(尽管128位):
UUID.randomUUID();
少一点适当(碰撞*是可能的)64位:
UUID.getLeastSignificantBits();
UUID.getMostSignificantBits();
要真正获得唯一的ID(如果他们是你的操作至关重要):
*碰撞=> 2个或更多相等的值