在 Java 中生成唯一随机数

2022-08-31 10:12:01

我试图得到0到100之间的随机数。但我希望它们是独一无二的,而不是按顺序重复。例如,如果我得到5个数字,它们应该是82,12,53,64,32,而不是82,12,53,12,32,我用这个,但它在序列中生成相同的数字。

Random rand = new Random();
selected = rand.nextInt(100);

答案 1
  • 列表结构中按顺序添加区域中的每个数字。
  • 洗牌它。
  • 取第一个“n”。

下面是一个简单的实现。这将打印范围为 1-10 的 3 个唯一随机数。

import java.util.ArrayList;
import java.util.Collections;

public class UniqueRandomNumbers {
    
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        for (int i=1; i<11; i++) list.add(i);
        Collections.shuffle(list);
        for (int i=0; i<3; i++) System.out.println(list.get(i));
    }
}

正如Mark Byers在现已删除的答案中指出的那样,使用原始方法修复的第一部分是仅使用单个实例。Random

这就是导致数字相同的原因。实例按当前时间设定种子(以毫秒为单位)。对于特定的种子值,“随机”实例将返回完全相同伪随机数序列。Random


答案 2

使用Java 8 +,您可以使用ints方法来获取随机值的IntStream,然后区分限制,以将流减少到许多唯一的随机值。Random

ThreadLocalRandom.current().ints(0, 100).distinct().limit(5).forEach(System.out::println);

Random还有一些方法可以创建s和s,如果你需要它们。LongStreamDoubleStream

如果您希望一个范围内的所有(或大量)数字以随机顺序排列,则将所有数字添加到列表中,对其进行随机排序并取第一个n可能会更有效,因为上述示例目前是通过在请求的范围内生成随机数并将它们传递到集合中来实现的(类似于Rob Kielty的答案)),这可能需要生成比传递到限制的量多得多的量,因为生成新唯一数字的概率随着每个发现而降低。下面是另一种方式的示例:

List<Integer> range = IntStream.range(0, 100).boxed()
        .collect(Collectors.toCollection(ArrayList::new));
Collections.shuffle(range);
range.subList(0, 99).forEach(System.out::println);

推荐