我想要获取0到100之间的随机数,但是我希望它们是唯一的,在序列中不会重复。例如,如果我获得了5个数字,它们应该是82、12、53、64、32,而不是82、12、53、12、32。我使用了以下代码,但它生成的数字在序列中是相同的。
Random rand = new Random();
selected = rand.nextInt(100);
这是一个简单的实现。这将从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
实例以毫秒为单位设置种子值。对于特定的种子值,'随机'实例将返回完全相同的伪随机数序列。
使用Java 8+,你可以使用Random
的ints
方法获取随机值的IntStream
,然后使用distinct
和limit
将流减少到一定数量的唯一随机值。
ThreadLocalRandom.current().ints(0, 100).distinct().limit(5).forEach(System.out::println);
Random
还有一些方法可以创建LongStream
和DoubleStream
,如果你需要的话。
如果你想要在一个范围内以随机顺序输出所有(或大量)数字,可能更有效的方法是将所有数字添加到列表中,然后打乱它们并取前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);
Arrays#setAll()
比流略快。所以:Integer [] indices = new Integer [n]; Arrays.setAll(indices,i-> i); Collections.shuffle(Arrays.asList(indices)); return Arrays.stream(indices).mapToInt(Integer :: intValue).toArray();
- AbuNassarlong
数组创建易于清除的布尔数组,其中您可以通过移位和掩码来访问各个位。)使用 Collections.shuffle()
对所有100个数字进行洗牌,然后选择前五个,可以参考这里和下面的示例。
控制台:
59 9 68 24 82
代码:
private static final Random rnd = new Random();
private static final int N = 100;
private static final int K = 5;
private static final List<Integer> S = new ArrayList<>(N);
public static void main(String[] args) {
for (int i = 0; i < N; i++) {
S.add(i + 1);
}
Collections.shuffle(S, rnd);
for (int i = 0; i < K; i++) {
System.out.print(S.get(i) + " ");
}
System.out.println();
}
我觉得这种方法值得一提。
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, i.e. 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;
}
我重新改进了Anand的答案,不仅利用了Set的独特属性,而且还使用了在集合添加失败时set.add()
返回的布尔值false。
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);
}
}
SET_SIZE_REQUIRED
足够大(比如说,超过了 NUMBER_RANGE / 2
),那么你将得到更长的预期运行时间。 - noamgot!= true
的比较方式。只需使用 while(set.add(random.nextInt(NUMBER_RANGE)) ;
并且始终使用泛型。不要创建一个 HashSet<Integer>
并将其分配给原始的 Set
。 - Holgerwhile(! set.add(random.nextInt(NUMBER_RANGE)) ;
… - Holger Random random = new Random();
ArrayList<Integer> arrayList = new ArrayList<Integer>();
while (arrayList.size() < 6) { // how many numbers u need - it will 6
int a = random.nextInt(49)+1; // this will give numbers between 1 and 50.
if (!arrayList.contains(a)) {
arrayList.add(a);
}
}
以下方法可用于生成唯一的随机数:
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的幂模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
void randInts() {
int num=1;
for (int ii=0; ii<101; ii++) {
System.out.println(num);
num= (num*2) % 101;
}
}
我来自另一个问题,该问题已被重复提交到这个问题(在 Java 中生成唯一的随机数)
将1至100的数字存储在数组中。
生成1至100之间的随机数作为位置,并返回array[position-1]以获取值
一旦使用了数组中的数字,请将该值标记为-1(无需维护另一个数组来检查此数字是否已使用)
如果数组中的值为-1,请再次获取随机数字以获取数组中的新位置。
1..100
范围内的 随机排列(有著名的算法可实现),但在确定前n
个元素后停止。 - Kerrek SB