从1到n之间抽取出k个不重复的随机数,用Math.random()实现的话,可参照下面的代码。
int r = (int) (Math.random() * n), 生成下标,据此下标,去到numbers数组里拿到随机数。然后将numbers[r]的值设置成numbers[n-1]的值,下次抽取时,从numbers数组的前n-1个元素里抽取。以此类推,再下次,就是从umbers数组的前n-2个元素里抽取,直到抽完k个为止。
每次生成的下标是有可能重复的,但是由于numbers数组里该下标对应的值每抽中一次,就被踢出去了(替换成了n-1位置上的值),所以最终结果并不会重复。interesting…
公司年会抽奖,可以这种方法,将numbers数组初始化成在职的员工号序列即可:-)
package com.company;
import java.util.Arrays;
import java.util.Scanner;
public class LotteryDrawing {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("How many numbers do you need to draw?");
int k = in.nextInt();
System.out.println("What is the highest number you can draw?");
int n = in.nextInt();
int[] numbers = new int[n];
for(int i = 0; i < n; i ++)
numbers[i] = i + 1;
int[] result = new int[k];
for(int i = 0; i < result.length; i ++){
//Math.random() generate double that between 0 and 1 (0 included, 1 not included)
//int r represents the index that between 0 and n-1 (both included)
int r = (int) (Math.random() * n);
result[i] = numbers[r];
numbers[r] = numbers[n-1];
n --;
}
Arrays.sort(result);
System.out.println("Lucky numbers: ");
for(int i : result)
System.out.println(i);
}
}
程序输出:
How many numbers do you need to draw?
6
What is the highest number you can draw?
20
Lucky numbers:
1
2
10
16
17
18
Java还有个Random类,用这个类也可以实现上述目标,基本思想是一样的。
package com.company;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
import java.util.List;
public class LotteryDrawing {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("How many numbers do you need to draw?");
int k = in.nextInt();
System.out.println("What is the highest number you can draw?");
int n = in.nextInt();
List<Integer> numbers = new ArrayList<>();
for(int i = 0; i < n; i ++)
numbers.add(i + 1);
int[] result = new int[k];
for(int i = 0; i < k; i ++){
int r = generateRandomIndex(n - i);
result[i] = numbers.get(r);
numbers.remove(r);
}
Arrays.sort(result);
System.out.println("Lucky numbers: ");
for(int i : result)
System.out.println(i);
}
private static int generateRandomIndex(int n){
Random random = new Random();
//return an int that between 0 and n, 0 included, n not included
return random.nextInt(n);
}
}
程序输出:
How many numbers do you need to draw?
6
What is the highest number you can draw?
20
Lucky numbers:
6
7
8
11
12
13
在创建Random实例时,如果给定一个种子数字,那么这个实例生成出来的序列是一定的。比如,给定种子数字1,每一次运行时,它生成出来的序列都是5,8,7,3,4。
Random random = new Random(1);
System.out.println(random.nextInt(10));
System.out.println(random.nextInt(10));
System.out.println(random.nextInt(10));
System.out.println(random.nextInt(10));
System.out.println(random.nextInt(10));
程序输出:
5
8
7
3
4
如果想要每次的序列不一样,那么新建实例时不要给种子数字,它会用系统时间作为种子数字(高并发的情况下,亦不能保证每次调用时系统时间都不一样…)
Random random = new Random();
System.out.println(random.nextInt(10));
System.out.println(random.nextInt(10));
System.out.println(random.nextInt(10));
System.out.println(random.nextInt(10));
System.out.println(random.nextInt(10));
第一次运行时程序输出:
7
9
4
0
3
第二次运行时程序输出
8
9
9
4
0