在Java中生成唯一的随机数

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

Random rand = new Random(); selected = rand.nextInt(100); 
  • 在列表结构中按顺序添加范围中的每个数字。
  • 随机播放 。
  • 拿第一个'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(new Integer(i)); } Collections.shuffle(list); for (int i=0; i<3; i++) { System.out.println(list.get(i)); } } } 

马克·比尔斯在回答中指出,原来的方法的第一部分是现在删除的答案是只使用一个单一的Random实例。

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

使用Java 8 +,您可以使用Randomints方法获取随机值的IntStream ,然后将其IntStream并将其limit为将数据stream简化为多个唯一的随机值。

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

Random也有创buildLongStreamDoubleStream的方法,如果你需要的话。

如果你想以一个随机的顺序在一个范围内的所有(或大量的)数字,把所有的数字加到一个列表中,洗牌,然后取第一个n可能会更有效率,因为上面的例子是当前实现的通过在请求的范围内产生随机数并将它们传递给一组(类似于Rob Kielty的回答 ),这可能需要产生比通过限制的数量多得多的数,因为产生一个新的唯一数的概率随着每个数的减less而减less。 这是另一种方式的例子:

 List<Integer> range = IntStream.range(0, 100).boxed() .collect(Collectors.toCollection(ArrayList::new)); Collections.shuffle(range); range.subList(0, 99).forEach(System.out::println); 
  1. 创build一个100个数字的数组,然后随机化他们的顺序。
  2. devise一个范围为100的伪随机数生成器。
  3. 创build一个由100个元素组成的布尔数组,然后在select该数字时设置true。 当你select下一个数字检查数组,并再次尝试,如果数组元素被设置。 (你可以用一个longarrays来清除一个易于清除的布尔数组,在这个布尔数组中,你移位和掩码来访问各个位。

在所有100个号码上使用Collections.shuffle() ,并select前五个,如下所示。

我重新考虑了Anand的答案,不仅要使用Set的唯一属性,还要使用set.add()返回的布尔值false,当添加到set失败时。

 import java.util.HashSet; import java.util.Random; import java.util.Set; public class randomUniqueNumberGenerator { public static final int SET_SIZE_REQUIRED = 10; public static final int NUMBER_RANGE = 100; public static void main(String[] args) { Random random = new Random(); Set set = new HashSet<Integer>(SET_SIZE_REQUIRED); while(set.size()< SET_SIZE_REQUIRED) { while (set.add(random.nextInt(NUMBER_RANGE)) != true) ; } assert set.size() == SET_SIZE_REQUIRED; System.out.println(set); } } 

我觉得这个方法值得一提。

  private static final Random RANDOM = new Random(); /** * Pick n numbers between 0 (inclusive) and k (inclusive) * While there are very deterministic ways to do this, * for large k and small n, this could be easier than creating * an large array and sorting, ie k = 10,000 */ public Set<Integer> pickRandom(int n, int k) { final Set<Integer> picked = new HashSet<>(); while (picked.size() < n) { picked.add(RANDOM.nextInt(k + 1)); } return picked; } 

我从另一个问题来到这里,这个问题已经被重复( 在Java中生成唯一的随机数 )

  1. 在数组中存储1到100个数字。

  2. 生成1到100之间的随机数作为位置并返回数组[position-1]以获取值

  3. 一旦在数组中使用了一个数字,将该值标记为-1(不需要维护另一个数组来检查这个数字是否已被使用)

  4. 如果数组中的值为-1,则再次获取该随机数以获取数组中的新位置。

这将产生独特的随机数字…………….

 import java.util.HashSet; import java.util.Random; public class RandomExample { public static void main(String[] args) { Random rand = new Random(); int e; int i; int g = 10; HashSet<Integer> randomNumbers = new HashSet<Integer>(); for (i = 0; i < g; i++) { e = rand.nextInt(20); randomNumbers.add(e); if (randomNumbers.size() <= 10) { if (randomNumbers.size() == 10) { g = 10; } g++; randomNumbers.add(e); } } System.out.println("Ten Unique random numbers from 1 to 20 are : " + randomNumbers); } } 

一个聪明的方法是使用模数中的原始元素的指数。

例如,2是一个原始根模101,意思是2 mod 101的幂赋给你一个非重复的序列,可以看到从1到100的所有数字:

 2^0 mod 101 = 1 2^1 mod 101 = 2 2^2 mod 101 = 4 ... 2^50 mod 101 = 100 2^51 mod 101 = 99 2^52 mod 101 = 97 ... 2^100 mod 101 = 1 

在Java代码中,你会写:

 void randInts() { int num=1; for (int ii=0; ii<101; ii++) { System.out.println(num); num= (num*2) % 101; } } 

find一个特定模数的原始根可能会很棘手,但枫的“primroot”函数会为你做这个。

试试这个

 public class RandomValueGenerator { /** * */ private volatile List<Double> previousGenValues = new ArrayList<Double>(); public void init() { previousGenValues.add(Double.valueOf(0)); } public String getNextValue() { Random random = new Random(); double nextValue=0; while(previousGenValues.contains(Double.valueOf(nextValue))) { nextValue = random.nextDouble(); } previousGenValues.add(Double.valueOf(nextValue)); return String.valueOf(nextValue); } } 

检查这个

 public class RandomNumbers { public static void main(String[] args) { // TODO Auto-generated method stub int n = 5; int A[] = uniqueRandomArray(n); for(int i = 0; i<n; i++){ System.out.println(A[i]); } } public static int[] uniqueRandomArray(int n){ int [] A = new int[n]; for(int i = 0; i< A.length; ){ if(i == A.length){ break; } int b = (int)(Math.random() *n) + 1; if(f(A,b) == false){ A[i++] = b; } } return A; } public static boolean f(int[] A, int n){ for(int i=0; i<A.length; i++){ if(A[i] == n){ return true; } } return false; } } 

从0到m-1中selectn个唯一的随机数。

 int[] uniqueRand(int n, int m){ Random rand = new Random(); int[] r = new int[n]; int[] result = new int[n]; for(int i = 0; i < n; i++){ r[i] = rand.nextInt(mi); result[i] = r[i]; for(int j = i-1; j >= 0; j--){ if(result[i] >= r[j]) result[i]++; } } return result; } 

想象一个包含从0到m-1的数字的列表。 要select第一个数字,我们只需使用rand.nextInt(m) 。 然后从列表中删除号码。 现在仍有m-1个数字,所以我们称之为rand.nextInt(m-1) 。 我们得到的数字代表列表中的位置。 如果它小于第一个数字,那么它是第二个数字,因为第一个数字之前的列表部分没有被第一个数字的移除所改变。 如果位置大于或等于第一个数字,第二个数字是位置+ 1。 做一些进一步的推导,你可以得到这个algorithm。