論 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"); 
    }

當測試數字越大越能體現出效果.

以上有不足的地方還請大家見諒!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM