【问题标题】:Generating java unique numbers randomly随机生成java唯一数字
【发布时间】:2013-06-24 08:16:23
【问题描述】:

我将实现唯一随机数生成器。但是在运行它时,它有时会生成与 previous 相同的数字。这种情况下如何保证生成的数字不重复?

下面是我的代码

    int refno = 0;

    SecureRandom r = new SecureRandom();
    refno = r.nextInt(999999999);

【问题讨论】:

  • 使用同步序列而不是随机序列。你不能用随机数创建唯一的数字...
  • 您可以将已经使用的随机数存储在一个集合中,如果您在该集合中找到生​​成的数字,则重复生成
  • 顺便说一句:当你想要“一个非常大的数字”时,你可以使用常量Integer.MAX_VALUE 而不是像999999999 这样的任意值。

标签: java random int


【解决方案1】:

RandomSecureRandom 返回一个随机数。随机数永远不是唯一的(否则它们就不是随机的)。

要创建唯一标识符,请使用 java.util.UUID 类。

【讨论】:

    【解决方案2】:

    随机数生成器在有限范围内创建数字,因此它迟早要重复自己。

    当您生成的数字范围较小时(例如,当您想模拟一副纸牌时),您可以创建一个包含所有可能值的列表,将其随机打乱并以现在的随机顺序返回元素。

     class UniqueRandom {
          private LinkedList<Integer> results;
    
          public UniqueRandom(int range) {
               results = new LinkedList<Integer>(range);
               for (var i = 0; i < range; i++) {
                    results.add(i);
               }
    
               Collection.shuffle(results, new SecureRandom());
          }
    
          public int nextInt() throws NoSuchElementException {
               return results.pop(); // will throw NoSuchElementException when all values are used up
          }
     }
    

    当由于范围太大而无法做到这一点时,您可以将已经生成的数字存储在一个集合中。在返回结果之前,检查它是否已经在该集合中,如果是,则重新滚动。

     class UniqueRandom {
          private Set<Integer> used = new HashSet<Integer>();
          private Random rand = new SecureRandom();
    
          public int nextInt(int max) {
              Integer ret = null;
              do {             
                 ret = rand.nextInt(max);
              } while (used.add(ret) == false); 
              return ret;
          }
     }
    

    警告:后一种算法会随着生成的数字越多越慢,最终会在所有值用完时进入无限循环,所以只有在你可以确定结果的范围永远不会用尽。或者,您可以检查used 的大小,并在它变得太大时抛出异常。

    【讨论】:

      【解决方案3】:

      您可以使用UUID

      UUID.randomUUID();
      

      由于 UUID 是 128 位数字,您必须将其转换为 BigInteger。

      【讨论】:

      • 我相信 UUID 是十六进制的(例如,我刚刚生成了一个,它是 02c9c6b0-2f9b-4ae5-a6e5-c2a2a59b4382),这是否会导致难以将其存储在 BigInteger 中?
      • 还有;为什么要转换它?
      • 好吧,如果他必须有一个整数表示。而且这并不难。看看 UUID API。它有long getMostSigBits()long getLeastSigBits() 方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-03
      • 2011-12-28
      • 2020-05-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多