Java程序生成一个唯一的和随机的六个alpha数字代码



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

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

有哪些可能的方法来实现这一点?

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

考虑使用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);

在字母数字字符集中有36个字符(0-9个数字+ a-z个字母)。有了6个位置,你得到366 = 2.176.782.336个不同的选项,这比231略大。

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

如果你不能保证这一点,你最终会在你的类中使用一个(同步的)计数器。此外,如果您想在JVM重启后存活下来,您应该保存当前值(例如保存到数据库、文件等,无论您有什么选项)。

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

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

  1. 生成随机的6个字符串
  2. 检查之前是否通过查询数据库生成了该字符串
  3. 如果你之前生成的,回到1
另一种方法是使用大小为32位的伪随机排列(PRP)。块密码被建模为PRP函数,但支持32位块大小的并不多。有些是由国家安全局和仓促布丁密码。例如,使用PRP,您可以获取一个已经唯一的值,例如数据库主密钥,并使用块密码对其进行加密。如果输入不大于32位,则输出仍然是唯一的。

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

如果是子字符串,则该值可能不是唯一的

更多信息请参见下面的类似链接生成仅8个字符的uuid

假设语料库是alpha数字字母的集合。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和的语料库,假设的分布是完全随机的。这样的话,我们就有生日问题了。这就得到了N = 62^6的可能性。我们想找到n,其中重复的机会在10%左右。

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

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

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

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

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

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

最新更新