0

可能的重复:
在 Java 中生成唯一的随机数

如何生成 0 到 1000 之间的随机数并继续将在 0 到 1000 之间生成的唯一随机数传递给特定方法。因此,为此我生成了 0 到 1000 之间的数字,并在 List 中插入了 0 到 1000 之间的唯一随机数,以便我们可以比较我们生成的随机数是否已经存在于列表中。如果它存在,则再次生成它。但不知何故,我相信下面的代码有时会失败。

public class Testing4 {
    private static List<Integer> randomNumber;
    private static Random r = new Random();
    private static int rand;
    private static int endRange = 1000;

    public static void main(String args[]) throws IOException {

        randomNumber = new ArrayList<Integer>();

        for (int i = 1; i<= endRange; i++) {
            rand = r.nextInt(endRange);

            if(randomNumber.contains(rand)) {
                rand = r.nextInt(endRange);
            } else {
                randomNumber.add(rand);
            }

        // Pass the unique random number between 0 and 1000 to this method      
                randomNumberMethod(rand);

        }
    }
}
4

4 回答 4

3

您实际上是在以随机顺序生成 0-1000 的数字列表。您可以通过以下方式更有效地实现这一目标:

public class Testing4 {
    private static List<Integer> randomNumber;
    private static int endRange = 1000;

    public static void main(String args[]) throws IOException {

        randomNumber = new ArrayList<Integer>(endRange);

        for (int i = 0; i<= endRange; i++) {                
            randomNumber.add(i);
        }

        Collections.shuffle(randomNumber);

        for (int i = 0; i<= endRange; i++) {                
            // Pass the unique random number between 0 and 1000 to this method      
            randomNumberMethod(randomNumber.get(i));
        }
    }
}

想想当你到达 999 时会发生什么——你将有 999 分之一的机会在每次循环中“猜测”剩余的可用数字。

于 2012-05-21T21:45:50.367 回答
2

要生成 0 到 1000 之间的唯一数字列表,请执行以下操作:

  • 创建一个包含从 0 到 1000 的所有数字的列表
  • 使用 Collections.shuffle() 打乱列表
  • 从列表中取出您需要的第一个数字。

在某些情况下需要更复杂的算法,但如果可能的数字范围和您需要选择的项目数量都在 1000 左右,那么您真的不妨从随机打乱的列表中取出前n 个数字所有的可能性。

如果您确实想做您建议的事情,那么:

  • 正如另一位海报所建议的那样使用while循环
  • 使用 Set 而不是列表来存储已经选择的值。

但是,这变得低效,因为要选择的项目数量趋向于可能项目的数量(例如,如果您从可能的 1000 个数字中选择 10 个,那么就可以了;如果您选择 900在可能的 1000 个中,它将变得低效,因为每次都需要拒绝越来越多的数字,然后才能找到以前未选择的数字)。

于 2012-05-21T21:40:12.210 回答
1

从代码检查中,我看不到任何会阻止它工作的方法,它只是非常低效。

一方面,检查数字是否是您看到的数字randomNumber.contains(rand)将花费越来越多的时间,因为您每次生成的数字越多,您必须将其与列表中的每个数字进行比较,直到您找到一个匹配的,或者您已经尝试了列表中的每个数字。更好的方法是使用 aHashSet而不是列表,它应该使每个成员资格测试花费相同的时间,而不管您在其中放入了多少东西。

通过注意您可能提出了错误的问题,可以进行第二个更重要的优化。您是要生成唯一的随机数,还是要以随机顺序生成 1 和 endRange 之间的每个数字?如果您想要每个数字(甚至是其中的重要部分),将 1 到 1000 之间的每个数字放入一个列表中,然后使用Collections.shuffle. 所以你的生成代码将是:

java.util.List<Integer> nums = new java.util.ArrayList<Integer>(1001);
for (int i = 0; i <= 1000; i++)
{
   nums.add(new Integer(i));
}
java.util.Collections.shuffle(nums);
于 2012-05-21T21:55:48.663 回答
0

如果连续生成 ArrayList 中已存在的 2 个数字,您的代码将失败。它将使用第二个数字,无论它是否重复。if 语句应该是一个 while 循环(不断尝试,直到它生成一个唯一的循环)。

public class Testing4 {
    private static HashSet<Integer> randomNumber;
    private static Random r = new Random();
    private static int rand;
    private static int endRange = 1000;

    public static void main(String args[]) throws IOException {

        randomNumber = new HashSet<Integer>();

        for (int i = 1; i<= endRange; i++) {    
            do
            {
               rand = r.nextInt(endRange);
            }
            while(randomNumber.contains(rand));

            randomNumber.add(rand);

            // Pass the unique random number between 0 and 1000 to this method      
            randomNumberMethod(rand);

        }
    }
}

编辑:根据评论,您应该使用 do/while 和散列数据结构而不是 arraylist 来加速重复查找。最后的编辑在上面的代码中。

于 2012-05-21T21:37:51.790 回答