public class RandomTask {
private List<Long> data;
private int n;
private int sum;
private int[] book;
private List<Long> result;
private Random random = new Random();
public RandomTask(int n, List<Long> idList){
this.n = n;
sum = idList.size();
book = new int[sum];
data = new ArrayList<>(idList.size());
for (int i = 0; i < sum; ) {
data.add(idList.get(i++));
}
result = new ArrayList<>(n);
}
public List<Long> gen(){
for (int i=0;i<n;i++){
int index = random.nextInt(sum);
//如果已取出,则需要再生成一个不重复的
while (book[index]==1){
index=random.nextInt(sum);
}
//将其标记为取出状态
book[index]=1;
result.add(data.get(index));
}
return result;
}
}
其中data和result可以是任意数据类型的List。
该算法的思想如下:
1.初始化原始数组data和新数组result以及判定数组book,data和book长度为sum,result长度自定义为n。
2.从data中随机产生[0,sum)之间的数字index。
3.判断book[index]是否为1,不是的话进入4,否则返回2。
4.将data[index]放进result末尾,并将book[index]设为1。
5.重复2-4直到result长度为n。
容易看出,当n和sum接近时,很容易出现重复,所以这个算法在从大量的数据中抽出一小部分的情况下比较适用,但当n和sum接近时效率非常低。