2015-09-15 30 views
2

我需要生成一个6字母数字字符的预留代码,这是Java中的随机和唯一。Java程序生成一个唯一的和随机的六个字母数字代码

尝试使用UUID.randomuuid().toString(),但是id太长,并且要求它只应该是6个字符。

有什么办法可以做到这一点?

只是为了澄清,(因为这个问题被标记为重复)。 我发现的其他解决方案只是简单地生成随机字符,这在这种情况下是不够的。我需要合理地确保随机代码不会再次生成。

+2

可能重复的[如何生成一个随机的字母数字字符串?](http://stackoverflow.com/questions/41107/how-to-generate-a-random-alpha-numeric-string) – Stanislav

回答

1

考虑使用hashids库生成一个整数盐腌哈希(数据库ID或其他随机整数可能更好)。

http://hashids.org/java/

Hashids hashids = new Hashids("this is my salt",6); 
String id = hashids.encode(1, 2, 3); 
long[] numbers = hashids.decode(id); 
-2

你可以尝试使你的生成的UUID的子串。

String uuid = UUID.randomUUID().toString(); 
System.out.println("uuid = " + uuid.substring(0,5); 
+0

此选项不确保值不被重用 –

0

如果你这样做值可能不以获得更多信息独特

的子串,请参阅以下类似的链接 Generating 8-character only UUIDs

+0

谢谢,但要求是严格的,它必须是6个字符。而且,链接中的这些解决方案似乎都不够安全。我知道它不能被100%保护,所以我更喜欢那些已经尝试和测试过的东西。 –

+0

@Mishal Harish您的安全意味着什么? – matt

1

尽管它的名字,UUID的不是唯一的。这是不太可能得到一个128位的冲突。使用6(小于32位),如果只是散列东西或生成随机字符串,很可能会发生冲突。

如果唯一性约束是必要的,那么你需要

  1. 生成一个随机的6字符串
  2. 检查,如果你之前生成的字符串,通过查询数据库
  3. 如果你之前产生的,去回到1

另一种方法是使用大小为32位的pseadorandom置换(PRP)。分组密码被建模为PRP函数,但没有多少支持32位块大小。有些是由美国国家安全局和速食布丁密码拍摄的。

通过PRP,您可以例如获取数据库主键等已经唯一的值,并使用分组密码对其进行加密。如果输入不大于32位,那么输出仍然是唯一的。

然后,您将在输出上运行Base62(或至少是Base 41)并删除填充字符以获得6个字符的输出。

2

字母数字字符集中有36个字符(0-9数字+ a-z字母)。有6个地方可以实现36 = 2.176.782.336不同的选项,略大于2 。

因此,您可以使用Unix time来创建唯一的ID。但是,您必须确保在同一秒内没有生成ID。

如果你不能保证,你最终会在你的班级中同步(同步)计数器。另外,如果您想要在JVM重新启动的情况下生存下来,您应该保存当前值(例如,保存到数据库,文件等等)。

0

可以说你的语料库是字母数字字母的集合。 a-zA-Z0-9

char[] corpus = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); 

我们可以使用SecureRandom生成种子,这将要求OS熵,这取决于操作系统。这里的诀窍是保持均匀分布,每个字节有255个值,但我们只需要大约62个,所以我会提出拒绝采样。

int generated = 0; 
int desired=6; 
char[] result= new char[desired]; 

while(generated<desired){ 
    byte[] ran = SecureRandom.getSeed(desired); 
    for(byte b: ran){ 
     if(b>=0&&b<corpus.length){ 
      result[generated] = corpus[b]; 
      generated+=1; 
      if(generated==desired) break; 
     } 
    } 
} 

改进可能包括更智能地包装生成的值。

我们什么时候可以重复?让我们坚持62和的语料库,假设的分布是完全随机的。在这种情况下,我们有birthday problem。这给我们带来了很大的可能性。我们希望找到n其中重复10%左右的机会。

p(r)= 1 - N!/(N^n (N-n)!) 

并使用维基百科页面中给出的近似值。

n = sqrt(-ln(0.9)2N) 

这给了我们109000个数字10%的几率。如果有0.1%的机会,它需要大约10000个数字。

+0

这是OP排除的这种随机解决方案,并不能保证唯一性。 – gaborsch

+0

@GaborSch“我需要合理地确保不会再生成一个随机码。”这几乎是完全随机的,这将是合理的unique_。该操作没有真正澄清。可能最好的结果是使用当前的时间戳,并将其散列到字符。这样它将是独一无二的,但不那么随意。 – matt

相关问题