Java程序生成一个独特的随机六字母数字代码

时间:2015-09-15 05:16:02

标签: java encryption uuid

我需要生成6个字母数字字符的预留代码,这在java中是随机且唯一的。

尝试使用UUID.randomuuid().toString(),但是ID过长,要求要求它只能是6个字符。

有哪些方法可以实现这一目标?

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

6 个答案:

答案 0 :(得分:2)

字母数字字符集中有36个字符(0-9位+ a-z字母)。有6个位置可以达到36 6 = 2.176.782.336个不同选项,略大于2 31

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

如果您无法保证,您最终会在班级中使用(同步)计数器。此外,如果您希望在JVM重新启动后继续存在,则应保存当前值(例如,保存到数据库,文件等等)。

答案 1 :(得分: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 :(得分:1)

尽管它的名字,UUID并不是唯一的。它极不可能发生128位冲突。使用6(小于32位)时,如果您只是散列内容或生成随机字符串,则很可能会发生冲突。

如果需要唯一性约束,则需要

  1. 生成一个随机的6个字符串
  2. 检查您之前是否通过查询数据库生成了该字符串
  3. 如果您之前生成过,请返回1
  4. 另一种方法是使用大小为32位的pseadorandom置换(PRP)。分组密码被建模为PRP功能,但是没有许多支持32位块大小。有些是NSA和Hasty Pudding Cipher的Speck。

    使用PRP,您可以采用类似数据库主键的已经唯一的值,并使用分组密码对其进行加密。如果输入不大于32位,则输出仍然是唯一的。

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

答案 3 :(得分:0)

如果您执行的子字符串值可能不唯一

了解更多信息,请参阅以下类似链接 Generating 8-character only UUIDs

答案 4 :(得分:0)

让我们说你的语料库是阿尔法数字字母的集合。 a-zA-Z0-9

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

我们可以使用SecureRandom生成一个种子,它将根据操作系统向操作系统询问熵。这里的技巧是保持均匀分布,每个字节有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 = 62 ^ 6 的可能性。我们希望找到 n ,其中重复的可能性大约为10%。

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

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

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

这给了我们大约109000个数字,10%的几率。有0.1%的几率可能需要大约10000个数字。

答案 5 :(得分:-2)

您可以尝试从生成的UUID中创建子字符串。

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