如何在Java中生成唯一的Long

如何在Java中生成唯一的Long,java,unique,uniqueidentifier,Java,Unique,Uniqueidentifier,我试图生成unqiue数字ID,用作Mysql数据库中的主键。由于系统的分布式特性,我需要在数据库之外生成它们 以下是我的尝试: @RunWith(MockitoJUnitRunner.class) 公共类抽象性测试{ @试验 public void testGenerateUniqueId(){ val id=new HashSet(); val duplicates=new HashSet(); 对于(int i=0;i

我试图生成unqiue数字ID,用作Mysql数据库中的主键。由于系统的分布式特性,我需要在数据库之外生成它们

以下是我的尝试:

@RunWith(MockitoJUnitRunner.class)
公共类抽象性测试{
@试验
public void testGenerateUniqueId(){
val id=new HashSet();
val duplicates=new HashSet();
对于(int i=0;i<1000000;i++){
val id=System.currentTimeMillis()+
(ThreadLocalRandom.current().nextLong(999999)+ThreadLocalRandom.current().nextLong(999999));
如果(!ids.add(id)){
副本。添加(id);
}
}
System.out.println(“id:+ids.size());
System.out.println(“副本:+Duplicates.size());
assertThat(重复).isEmpty();
}
}
结果是:

ids: 967265
Duplicates: 31939
ids: 1000000
Duplicates: 0
Iteration 1 of 5
ids: 30000000
Duplicates: 0
Iteration 2 of 5
ids: 30000000
Duplicates: 0
Iteration 3 of 5
ids: 30000000
Duplicates: 0
Iteration 4 of 5
ids: 30000000
Duplicates: 0
Iteration 5 of 5
ids: 30000000
Duplicates: 0
有人能推荐一种更好的方法来生成Java中真正独特的
long


解决办法似乎是:

@测试
public void testGenerateUniqueId_with uuid(){
val id=new HashSet();
val duplicates=new HashSet();
对于(int i=0;i<1000000;i++){
val id=UUID.randomuid().getMostSignificantBits()&Long.MAX_值;
如果(!ids.add(id)){
副本。添加(id);
}
}
System.out.println(“id:+ids.size());
System.out.println(“副本:+Duplicates.size());
assertThat(重复).isEmpty();
}
结果是:

ids: 967265
Duplicates: 31939
ids: 1000000
Duplicates: 0
Iteration 1 of 5
ids: 30000000
Duplicates: 0
Iteration 2 of 5
ids: 30000000
Duplicates: 0
Iteration 3 of 5
ids: 30000000
Duplicates: 0
Iteration 4 of 5
ids: 30000000
Duplicates: 0
Iteration 5 of 5
ids: 30000000
Duplicates: 0

以下是3000万代的5次迭代:

@测试
public void testGenerateUniqueId_with uuid(){
val迭代次数=5次;
对于(int j=0;j
结果是:

ids: 967265
Duplicates: 31939
ids: 1000000
Duplicates: 0
Iteration 1 of 5
ids: 30000000
Duplicates: 0
Iteration 2 of 5
ids: 30000000
Duplicates: 0
Iteration 3 of 5
ids: 30000000
Duplicates: 0
Iteration 4 of 5
ids: 30000000
Duplicates: 0
Iteration 5 of 5
ids: 30000000
Duplicates: 0

我添加了当前时间(以毫秒为单位),以帮助实现运行进程之外的唯一性

@测试
public void testGenerateUniqueId_with uuid_和currentTimeMillimes(){
val迭代次数=5次;
val duplicates=new HashSet();
对于(int j=0;j
如果可能的话,我建议您切换到,我认为这更适合您的目的。 使用UUID,您只需执行以下操作:

UUID uuid = UUID.randomUUID();


考虑到UUID几乎是唯一的,您可以使用UUID并将其转换为长代码

long uniqueNum = UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE
如果您想不受限制地实现唯一性,并且能够将id转换为字符串,那么您可以使用

String uniqueId = UUID.randomUUID().toString();

“我需要在数据库之外生成它们,因为系统是分布式的。”如果系统是分布式的,但它们都共享一个数据库,那么数据库就是生成ID的地方。MySQL可以自动生成顺序整数ID。让多个不同的进程生成ID只会导致冲突。@Michael不幸的是,ORM层不能很好地处理自动生成的ID。我们所看到的是,当使用自动增量ID时,相同的ID被分配给不同服务上的多个实体,这些实体保持相同的对象类型。这是一个XY问题。您应该问“如何让ORM框架能够很好地处理自动生成的ID”。我不敢相信任何值得使用的ORM框架都会在这个难以置信的基本用例中挣扎。很可能是你做错了。你为什么要生成随机数?单调递增序列有问题吗?我想随机性正在给你当前的难题增加它自己。你的问题没有提到任何关于随机性的需要。@ernest_k出于安全考虑,理想情况下。但我认为如果必须的话,我们可以和sequencial一起生活。但我怀疑我们在跨服务同步下一个可用id时也会遇到类似的问题?如果您不能对问题发表评论,正确的做法是通过发布非边界评论的答案来建立足够的声誉,以便能够这样做。评论的代表上限很低,不需要很长时间。这似乎可以做到——1000000次迭代中没有重复。不,你不能用这种方式将UUID转换为long,并且仍然保持属性“唯一”。值得讨论的是,这种转换会使结果的唯一性降低多少。“唯一输入+某些转换=唯一输出”的逻辑是错误的。如果转换将每个字符替换为?@crmepham,从初始化为0的整数变量开始,每次添加1,那么也将保证1000000次迭代中没有重复的字符。这并不能证明它在多个进程中足够健壮。@Michael,是的,但我需要保证每个服务不会按顺序分配下一个可用的编号。