论 Java 中获取一组不重复的随机数之性能问题

今天在做一个Java项目, 用到了使用一组不重复的随机数问题, 不管怎么做随机数里面总有几个是重复的.

于是上网去找资料, 在网上找到的资料中大部分都是一个思路:

网上的思路一:(性能不理想)

先生成一个随机数, 然后在生成下一个随机数的时候和以前的随机数进行匹配, 如果里面有当前生成的随机数, 那么重新去生成, 直到之前所生成的随机数组中没有当前所生成的那个数字为止. 这样做虽然能实现生成一组不重复的随机数, 但是性能不是很理想, 假如我们需要生成10个数字, 在生成第一的时候, 不用匹配, 在生成第二的时候和第一个匹配, 由于是随机数, 那么他的重复几率为 1 /10, 生成第三个的时候和第一个第二个进行匹配, 他的重复几率为 2 /10, 在生成最后一个的时候要和之前的前9个进行匹配, 那么最后一个生成的数就有 9 / 10 的几率和之前的数字重复, 由于10分之9的几率已经接近了1, 也就是说, 生成随机数的时候越往后重复的几率越接近1, 需要重新生成的次数越多,性能越差.

我分析的思路二:

我的思路是, 只生成一次随机数作为模板, 里面是有重复的, 在生成的过程中把这组数字按顺序放到一个集合里, 然后把这组随机数和集合中的数进行匹配, 把在集合中存在的那些随机数给移除掉, 那么集合中就剩下了随机数组中没有的数字了, 最后把随机数组中两个重复的最后一个数字换成集合中的第一个数字, 再把集合的第一个移除掉, 如此类推, 直到集合中的数字用完为止.

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        //网上方法获取不重复随机数
        testA(10000);
        //自定义方法获取不重复随机数
        testB(10000);
    }

    //自定义方法获取不重复随机数
    private static void testB(int sz){
        long startTime=System.currentTimeMillis(); //开始测试时间
        Random rd = new Random();
        int[] rds = new int[sz];//随机数数组
        int n = 0;//序号
        List<Integer> lst = new ArrayList<Integer>();//存放有序数字集合
        //获取随机数数组, 里面有重复数字
        while (n < rds.length) {
            lst.add(n);
            rds[n++] = (int)(rd.nextFloat() * sz);
        }
        //把随机数和有序集合进行匹对, 把随机数在集合出现的数字从集合中移除掉.
        for (int i = 0; i < rds.length; i++) {
            for (int j = 0; j < lst.size(); j++) {
                if (rds[i] == lst.get(j)) {
                    lst.remove(j);
                    break;
                }
            }
        }
        //把数组中重复的第二个数字用集合的第一个数字替换掉, 并移除掉数组的第一个数字
        for (int i = 0; i < rds.length; i++) {
            for (int j = 0; j < rds.length; j++) {
                if (i != j && rds[i] == rds[j]) {
                    rds[j] = lst.get(0);
                    lst.remove(0);
                    break;
                }
            }
        }
        //得到的  rds  数组就是不重复的随机数组
        long endTime=System.currentTimeMillis(); //获取结束时间
        System.out.println("自定义代码运行时间: "+(endTime-startTime)+"ms");
    }
    //网上方法获取不重复随机数
    private static void testA(int sz){
        long startTime=System.currentTimeMillis(); //开始测试时间
        Random random = new Random();
        int a[] = new int[sz];
        for (int i = 0; i < a.length; i++) {
            a[i] = random.nextInt(sz);
            for (int j = 1; j < i; j++) {
                while (a[i] == a[j]) {//如果重复,退回去重新生成随机数
                    i--;
                }
            }
        }
        long endTime=System.currentTimeMillis(); //获取结束时间
        System.out.println("网上思路代码运行时间: "+(endTime-startTime)+"ms");
    }

当测试数字越大越能体现出效果.

以上有不足的地方还请大家见谅!

时间: 10-25

论 Java 中获取一组不重复的随机数之性能问题的相关文章

js获取一组不重复的随机数的方法

一.基本思路: 建立一个数组,每次随机取走一个,放到新的数组中. 二.实现方法 1.方法一: (1)创建一个数组arr,数组元素为所有可能出现元素的集合: (2)通过num=Math.floor(Math.random()*num_total*first_value)方法获取随机数. 随机数的范围为0-arr.length; (3)通过push[num]获取数组该位置的元素: (4)通过arr.splice(num,1)删除该元素: 完整写法为: function roa(ar) { var a

JAVA中获取项目文件路径

在java中获得文件的路径在我们做上传文件操作时是不可避免的. web 上运行 1:this.getClass().getClassLoader().getResource("/").getPath(); this.getClass().getClassLoader().getResource("").getPath();  得到的是 ClassPath的绝对URI路径.如:/D:/jboss-4.2.2.GA/server/default/deploy/hp.wa

java中获取系统属性以及环境变量

java中获取系统属性以及环境变量 System.getEnv()和System.getProperties()的差别 从概念上讲,系统属性 和环境变量 都是名称与值之间的映射.两种机制都能用来将用户定义的信息传递给 Java 进程.环境变量产生很多其它的全局效应,由于它们不仅对Java 子进程可见,并且对于定义它们的进程的全部子进程都是可见的.在不同的操作系统上,它们的语义有细微的区别,比方,不区分大写和小写.由于这些原因,环境变量更可能有意料不到的副作用.最好在可能的地方使用系统属性.环境变

JAVA中获取系统时间

一. 获取当前系统时间和日期并格式化输出: import java.util.Date;import java.text.SimpleDateFormat; public class NowString {public static void main(String[] args) { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式System.out.println(df.forma

JAVA中获取当前系统时间及格式转换

JAVA中获取当前系统时间 一. 获取当前系统时间和日期并格式化输出: import java.util.Date;import java.text.SimpleDateFormat; public class NowString {public static void main(String[] args) { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式System.out.pr

Java中获取键盘输入值的三种方法

Java中获取键盘输入值的三种方法     Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值的现成函数!Java没有提供这样的函数也不代表遇到这种情况我们就束手无策,请你看以下三种解决方法吧: 以下将列出几种方法: 方法一:从控制台接收一个字符,然后将其打印出来 import java.io.*; public static void main(String [] args) throws

java中获取环境变量

分为获取java自身的一些环境变量和和操作系统相关的环境变量. 获取JVM相关的一些变量 在运行时设置一个环境变量 debug 为 true: java -Ddebug=true YourClass在程序中设置一个环境变量 debug 为 true: System.setProperty( "debug", "true" );获取一个环境变量 debug : String debug = System.getProperty( "debug" )

java中获取路径的几种方式

总是忘记, 备份一下,方便下次用. 第一种: File directory = new File("");//参数为空 String courseFile = directory.getCanonicalPath() ;System.out.println(courseFile); 结果:C:\Documents and Settings\Administrator\workspace\projectName获取当前类的所在工程路径; 第二种: File f = new File(th

java中获取日期和时间的方法总结

1.获取当前时间,和某个时间进行比较.此时主要拿long型的时间值. 方法如下:  要使用 java.util.Date .获取当前时间的代码如下 Date date = new Date(); date.getTime() ; 还有一种方式,使用 System.currentTimeMillis() ;都是得到一个当前的时间的long型的时间的毫秒值,这个值实际上是当前时间值与1970年一月一号零时零分零秒相差的毫秒数 一.获取当前时间,   格式为:   yyyy-mm-dd   hh-mm