在面试的时候有时候会被问到这样的问题,如何在最短时间内创建50w条不重复且随机的数? 这里给出三个方法(方法肯定不止这三种)
利用Set集合不重复的特点,我们可以Random一个数,往Set中插入数据,直到Set集合的大小满足我们要的数量
public static void aa(int n){
Set r = new LinkedHashSet(n);
Random random = new Random();
while (r.size() < n ) {
int i = random.nextInt(n );
r.add(i);
}
System.out.println(Arrays.toString(r.toArray()));
}
我们选n=10看看效果
public static void main(String[] args) {
int n = 10;
long a = Clock.systemDefaultZone().millis();
aa(n);
long b = Clock.systemDefaultZone().millis();
System.out.println("完成.时间是:"+(b-a));
}
这个也是无意中发现的
public static void bb(int n ){
List<Integer> r = new Random().ints(0, n).distinct().limit(n).boxed().collect(Collectors.toList());
System.out.println(Arrays.toString(r.toArray()));
}
直接循环生成一个1到50w的数组应该是最简单最有效率的,但是要满足随机的条件,还得给他换顺序
public static void cc(int n){
int[] x = new int[n];
for(int i = 0; i < n; i++)
{
x[i] = i;
}
Random r = new Random();
for(int i = 0; i < n; i++)
{
int in = r.nextInt(n - i) + i;
int t = x[in];
x[in] = x[i];
x[i] = t;
}
System.out.println(Arrays.toString(x));
}
重头戏自然就是比较三个方法的快慢了,先试试50w
public static void main(String[] args) {
int n = 500000;
long a = Clock.systemDefaultZone().millis();
aa(n);
long b = Clock.systemDefaultZone().millis();
System.out.println("第一张完成.时间是:"+(b-a));
long a1 = Clock.systemDefaultZone().millis();
bb(n);
long b1 = Clock.systemDefaultZone().millis();
System.out.println("第二种完成.时间是:"+(b1-a1));
long a2 = Clock.systemDefaultZone().millis();
cc(n);
long b2 = Clock.systemDefaultZone().millis();
System.out.println("第三种完成.时间是:"+(b2-a2));
}
可以看到第三种是时间最短的,只要15毫秒.第二种比第一种快了一倍,但是一开始数量少的时候却比第一种慢一些
这是因为第一种往Set中插入数据的时候,数据量越大,耗时越久,比如50w的数据,到499999的时候,需要在50w的数里面,Random一个唯一的数出来才能结束,概率也就是1/50w,而且每次Random的数都可能会一样,也就是说在50w个球里面,你伸手进去找一个球,没找到,把球返回去再拿一个球,运气不好拿一年都可能…
第二种其实原理也跟第一种类似,只是java8的Stream流操作进行了一些封装和处理.所以不推荐
在尝试1kw的数的时候, 第一种整整花了25605
毫秒,第二种25610
毫秒,第三种565
毫秒