如何在Java中生成唯一ID(整数)?

28

如何在Java中生成不可预测的整数唯一标识符?


9
也许你应该更加准确地说明你需求的背景。 - svachon
11个回答

57

需要多独特?

如果它只需要在一个进程中是独特的,那么你可以使用AtomicInteger并且每次需要新值时调用incrementAndGet()


1
最好使用Integer.MIN_VALUE来初始化AtomicInteger。这有助于调试并提供更多的数字供您使用。 - reccles
4
还需要考虑溢出的情况。例如 if (curInt == Integer.MAX_INT),则重置 atomicInteger。 - Dmitry Zagorulkin

9
int uniqueId = 0;

int getUniqueId()
{
    return uniqueId++;
}

如果您希望它是线程安全的,请添加synchronized

2
可能需要添加一个异常处理,以防整数过大而溢出。此外,可能需要从Integer.MinInt()(方法名称类似于此)开始设置uniqueId。 - sixtyfootersdude
1
只有当进程永远不停止运行时,这才有效。对于重新启动的应用程序,每次都会从0开始。 - talonx
好的,一开始可能会考虑使用Long而不是Integer。 - Jan Bodnar

8
 import java.util.UUID;

 public class IdGenerator {
    public static int generateUniqueId() {      
        UUID idOne = UUID.randomUUID();
        String str=""+idOne;        
        int uid=str.hashCode();
        String filterStr=""+uid;
        str=filterStr.replaceAll("-", "");
        return Integer.parseInt(str);
    }

    // XXX: replace with java.util.UUID

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            System.out.println(generateUniqueId());
            //generateUniqueId();
        }
    }

}

希望这能帮到您。

3
尽管UUID一定会提供唯一值,但不能保证当你对其进行哈希码处理时,它的独特性持续存在。你可以选择在Integer.MIN_VALUE和Integer.MAX_VALUE之间随机选取一个数字,然后希望得到最好的结果。 - Simon Nickerson
1
不是这样的。UUID.randomUUID()使用密码学强随机数生成器,因此应该比使用较弱的伪随机数生成器更好。 - Christopher Barber

4

如果你受到某些限制,那么这很容易做到。

如果只有一个线程,你只需要使用uniqueID++;确保在退出时存储当前的uniqueID。

如果有多个线程,可以使用常见的同步生成唯一ID的方法(与上述实现相同)。

问题是当你拥有许多CPU时——例如在集群或点对点游戏等分布式设置中。

在这种情况下,通常可以将两个部分组合成一个单独的数字。例如,每个生成唯一ID的进程都可以被分配一个自己的2字节ID号码,然后与uniqueID++组合起来。类似这样:

return (myID << 16) & uniqueID++

分发“myID”部分可能有些棘手,但有一些方法。您可以从集中式数据库中抓取一个,从集中式服务器请求唯一ID,...

如果您有一个Long而不是Int,其中一个常见的技巧是获取ETH0的设备ID(UUID),这保证是服务器唯一的--然后只需添加序列号即可。


2
如果你真的指的是整数而不是int:
Integer id = new Integer(42); // will not == any other Integer

如果您希望在JVM外部对其他进程或用户可见,具有持久性或其他考虑因素,则有其他方法,但是如果没有上下文,您最好使用系统内置的对象标识的唯一性。


1

只需生成ID并检查它是否已经存在于您生成的ID列表中。


1

那不会返回一个整数。格式是十六进制字符串,例如 20e8f3d6-3f8d-475b-8c19-9619a78bbdc8 - BalusC
1
@BalusC:你所说的只是字符串输出。在内部,UUID是一个128位的值,因此可以被解释为整数(尽管是BigInteger)。 - Adamski
1
仍然无法适应整数。 - BalusC

1

你需要它是:

  • 在同时运行的两个JVM之间唯一。
  • 即使JVM重新启动也是唯一的。
  • 线程安全的。
  • 支持null吗?如果不支持,使用int或long。

Bill K.为第一种情况提供了解决方案,即如果想让ID在2个JVM之间唯一。确保ID即使在JVM重新启动后也是唯一的正确方法是什么? - user1071840
哦,从集中式数据库之一请求唯一标识符也可以在重启后工作。 - user1071840

0

假设你有一个名为“员工”的类,具有以下属性:

public class Employee {
    
    private final String name;
    private int id;
    private static int nextID = 1;
    
    public Employee(String name) {
        this.name= name;
        id = nextID++;
    }
}

非常简单


0

如果只需要 int,那么 AtomicInteger 可以实现。

如果需要 String,则可以通过混合 timeStamp 和 AtomicLong 来使用下面的代码。

AtomicLong idCounter =  new AtomicLong(100);
long timestamp = System.currentTimeMillis();
long nextLong = idCounter.incrementAndGet();
String randomId = String.valueOf(timestamp)+String.valueOf(nextLong); 

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