如何生成固定长度的随机数而不会发生冲突?

时间:2019-09-12 06:34:18

标签: java random

我正在开发一个必须生成诸如 Google课堂之类的代码的应用程序。当用户创建课程时,我会使用以下功能生成代码

 private String codeGenerator(){
        StringBuilder stringBuilder=new StringBuilder();
        String chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        int characterLength=chars.length();
        for(int i=0;i<5;i++){
            stringBuilder.append(chars.charAt((int)Math.floor(Math.random()*characterLength)));
        }
        return stringBuilder.toString();
    }

我有62个不同的字符。我可以生成总计很大的 5 ^ 62 代码。我可以在服务器或用户设备中生成此代码。所以我的问题是哪种方法更好?生成的代码与其他代码冲突的可能性有多大?

4 个答案:

答案 0 :(得分:2)

从评论看来,您似乎正在为自己的应用程序生成组代码。

对于您的应用程序的用途和规模,可能需要5个字符的代码。但是,您应该知道几点:

  • 随机数生成器不用于生成唯一数字。您可以像现在一样生成随机代码,但是在将该代码视为唯一代码之前,应检查该代码的唯一性(例如,对照存储了已生成组代码的表进行检查)。
  • 如果希望用户输入组代码,则应包括一种检查组代码是否有效的方法,以避免用户意外加入与预期不同的组。这通常是通过在组码的末尾添加一个所谓的“校验和数字”来完成的。另请参见this answer
  • 您似乎正在尝试生成难以猜测的代码。在这种情况下,Math.random()很不适合(java.util.Random也是如此),尤其是因为组代码太短了。请改用安全的随机生成器,例如java.security.SecureRandom(对于您来说,很幸运,其安全性问题已在Android 4.4中得到解决,正如我从您的评论中看到的那样,它是您的应用程序支持的最低Android版本;请参阅还有this question)。另外,如果可能,请增加组代码的长度,例如8或12个字符。

有关更多信息,请参见Unique Random Identifiers


还有另一个问题。如果5个字符的组代码是唯一授予该组访问权限的东西,则存在严重的安全问题。理想情况下,应该有其他形式的授权,例如仅允许登录用户或某些登录用户—

  • 通过该组代码访问该组,或者
  • 接受通过该群组代码加入群组的邀请(例如,在Google课堂中,当用户尝试接受加入课程的邀请时,会引发PERMISSION_DENIED错误代码)。

答案 1 :(得分:1)

避免方案中重复的唯一方法是保留已生成的副本的副本,并避免“生成”任何会导致重复的内容。由于5 ^ 62很大,因此,如果使用数据库,则可以将它们存储在表上;或在哈希集上(如果所有内容都在内存中并且只有一个应用程序实例)(记住,每次创建新ID时都会将生成的ID列表保存到磁盘,并在启动时重新读取它)。

发生碰撞的可能性很低:您需要生成大约5^(62/2) = 5^31 ~= 4.6E21个真正随机的标识符,以使碰撞更有可能发生(请参阅birthday paradox)-这会花费很多时间存储空间并检查所有这些标识符是否重复,以检测是否存在这种情况。但这就是安全的代价。

答案 2 :(得分:0)

队列:一个麻袋包含一个蓝色的球和一个红色的球。我从麻袋里抽出一个球。红球有什么机会?

答案: 1/2


队列:我收集了5 ^ 62个唯一代码。我从集合中选择一个代码。它是“ ABCDE”的机会是什么?

答案: 1 /(5 ^ 62)

注意::随机数生成器不是actually random

答案 3 :(得分:0)

好吧,如果您需要一个唯一的生成器,那么接下来呢?这绝对不是随机的,但对于一个实例绝对是唯一的。

public final class UniqueCodeGenerator implements Supplier<String> {

    private int code;

    @Override
    public synchronized String get() {
        return String.format("%05d", code++);
    }

    public static void main(String... args) {
        Supplier<String> generator = new UniqueCodeGenerator();

        for (int i = 0; i < 10; i++)
            System.out.println(generator.get());
    }

}