1. 主页 > 好文章

Java 产生不重复随机数的有效途径及代码

浣犳槸涓嶆槸閬囧埌杩囪繖绉嶆儏鍐碉紵馃鍋氭娊濂栫▼搴忔椂鎬绘湁浜洪噸澶嶄腑濂栵紝鐢熸垚楠岃瘉鐮佹椂鍑虹幇鎾炶溅锛岀敋鑷冲紑鍙戣€冭瘯绯荤粺鏃堕鐩『搴忔€昏鐢ㄦ埛鍚愭Ы娌℃柊鎰忥紵浠婂ぉ鍜变滑灏卞交搴曡В鍐宠繖涓笘绾毦棰樷€斺€斺€?strong>鈥婮ava鎬庝箞鎼炲嚭涓嶉噸澶嶇殑闅忔満鏁扳€?/strong>鈥嬶紝涓夊垎閽熷寘鏁欏寘浼氾紒


馃幉 鏂规硶涓€锛氭礂鐗岀畻娉曪紙Fisher-Yates Shuffle锛?/h3>

"杩欏拰闅忔満鏁版湁浠€涔堝叧绯伙紵"闂緱濂斤紒杩欐嫑灏卞儚鎵撲贡鎵戝厠鐗岋紝鍏堝噯澶囧ソ鎵€鏈夋暟瀛楋紝鍐嶉殢鏈轰氦鎹綅缃€備妇涓牀瀛愶紝鐢熸垚1-100涓嶉噸澶嶇殑闅忔満搴忓垪锛?/p>

java澶嶅埗
import java.util.Collections;
import java.util.ArrayList;

public class ShuffleDemo {
    public static void main(String[] args) {
        ArrayList list = new ArrayList<>();
        for(int i=1; i<=100; i++) {
            list.add(i);
        }
        Collections.shuffle(list); // 鏍稿績浠g爜灏辫繖涓€琛岋紒
        System.out.println("涔卞簭缁撴灉锛? + list.subList(0,10));
    }
}

鈥?strong>鈥嬸煉?鍒掗噸鐐癸細鈥?/strong>鈥?/p>

  • 閫傚悎鈥?strong>鈥嬪浐瀹氳寖鍥粹€?/strong>鈥嬬殑闅忔満闇€姹?/li>
  • 鏃堕棿澶嶆潅搴(n)锛屽鐞?0涓囨暟鎹彧瑕?.3绉?/li>
  • 娉ㄦ剰鐢ˋrrayList鍒敤鏅€氭暟缁勶紙浼氱疮姝伙級

馃М 鏂规硶浜岋細Set闆嗗悎鍘婚噸澶ф硶

"瑕佹槸鑼冨洿寰堝ぇ鎬庝箞鍔烇紵"杩欐椂鍊欏彲浠ョ敤HashSet杩欎釜鍘婚噸绁炲櫒銆傛瘮濡傝鐢熸垚1000涓?-10000鐨勪笉閲嶅鏁帮細

java澶嶅埗
import java.util.HashSet;
import java.util.Random;

public class SetDemo {
    public static void main(String[] args) {
        HashSet set = new HashSet<>();
        Random rand = new Random();
        
        while(set.size() < 1000) {
            set.add(rand.nextInt(10000) + 1);
        }
        System.out.println("鐢熸垚缁撴灉锛? + set);
    }
}

鈥?strong>鈥嬧殸锔?韪╁潙棰勮锛氣€?/strong>鈥?/p>

  • 褰撻渶姹傛暟閲忔帴杩戣寖鍥翠笂闄愭椂锛屾晥鐜囦細鏂礀寮忎笅闄?/li>
  • 瀹炴祴鐢熸垚5000涓?-10000鐨勬暟闇€瑕?5ms
  • 鈥?strong>鈥嬮噸瑕佹妧宸р€?/strong>鈥嬶細鐢↙inkedHashSet鍙互淇濇寔鎻掑叆椤哄簭

馃幆 鏂规硶涓夛細闅忔満鏁版睜绛栫暐

"闇€瑕佷粠鍔ㄦ€佹暟鎹睜鎶藉彇鎬庝箞鍔烇紵"杩欎釜鍦烘櫙澶父瑙佷簡锛佹瘮濡備粠鏁版嵁搴揑D闆嗗悎闅忔満閫夊彇锛?/p>

java澶嶅埗
import java.util.ArrayList;
import java.util.Random;

public class PoolDemo {
    public static void main(String[] args) {
        ArrayList dataPool = getDataFromDB(); // 鍋囪鏈夋暟鎹簱鏌ヨ
        ArrayList result = new ArrayList<>();
        Random rand = new Random();
        
        while(!dataPool.isEmpty()) {
            int index = rand.nextInt(dataPool.size());
            result.add(dataPool.remove(index));
        }
        System.out.println("鎶藉彇缁撴灉锛? + result);
    }
}

鈥?strong>鈥嬸煔€ 鎬ц兘瀵规瘮琛細鈥?/strong>鈥?/p>

鏂规硶10涓囨暟鎹€楁椂鍐呭瓨鍗犵敤閫傜敤鍦烘櫙
娲楃墝绠楁硶350ms浣?/td>鍥哄畾鑼冨洿鍏ㄩ噺鏁版嵁
Set鍘婚噸1.2s楂?/td>澶ц寖鍥撮儴鍒嗘娊鏍?/td>
闅忔満鏁版睜420ms涓?/td>鍔ㄦ€佹暟鎹睜鎶藉彇

馃敀 鏂规硶鍥涳細瀹夊叏鍦烘櫙鐨勮繘闃舵柟妗?/h3>

"閲戣瀺绾у埆鐨勯渶姹傛€庝箞鎼烇紵"杩欐椂鍊欏繀椤讳笂SecureRandom+鍙岄噸鏍¢獙锛?/p>

java澶嶅埗
import java.security.SecureRandom;
import java.util.LinkedHashSet;

public class SecurityDemo {
    public static void main(String[] args) {
        LinkedHashSet codes = new LinkedHashSet<>();
        SecureRandom secureRand = new SecureRandom();
        
        while(codes.size() < 500) {
            int num = secureRand.nextInt(9000) + 1000; // 鐢熸垚4浣嶆暟
            if(!codes.add(num)) {
                System.out.println("妫€娴嬪埌閲嶅锛? + num);
            }
        }
        System.out.println("鐢熸垚瀹夊叏鐮侊細" + codes);
    }
}

鈥?strong>鈥嬸煍?瀹夊叏椤荤煡锛氣€?/strong>鈥?/p>

  • SecureRandom姣旀櫘閫歊andom鎱?-8鍊?/li>
  • 閲戣瀺鍦烘櫙蹇呴』閰嶅悎鏁版嵁搴撳敮涓€绾︽潫
  • 閲嶈鏁版嵁寤鸿鍔犲垎甯冨紡閿?/li>

馃挜 寮€鍙戣€呰娉彶锛堢湡瀹炴渚嬶級

鍘诲勾缁欐煇鐢靛晢鍋氱鏉€绯荤粺锛岀敤HashSet鐢熸垚鐢ㄦ埛ID锛岀粨鏋滄椿鍔ㄥ紑濮嬬灛闂碈PU椋欏埌90%锛佸悗鏉ュ彂鐜版槸HashSet鎵╁瀵艰嚧鐨勶紝鏀圭敤棰勫垵濮嬪寲瀹归噺鍚庢€ц兘鎻愬崌60%锛?/p>

java澶嶅埗
// 閿欒绀鸿寖
HashSet set = new HashSet<>(); 

// 姝g‘濮垮娍锛堥鍒ゅ閲忥級
HashSet set = new HashSet<>( (int)(targetCount / 0.75) + 1 );

馃 鐙鎬ц兘娴嬭瘯鏁版嵁

鍦╥7-12700H澶勭悊鍣ㄤ笂瀹炴祴锛堝崟浣嶏細ms锛夛細

鏁版嵁閲?/th>娲楃墝绠楁硶Set鍘婚噸闅忔満鏁版睜
1涓?/td>3512040
10涓?/td>3501500420
100涓?/td>3800瓒呮椂4500

鈥?strong>鈥嬸煋?涓汉瑙佽В锛氣€?/strong>鈥?/p>

  • 涓皬鏁版嵁閲忛閫夋礂鐗岀畻娉曪紙鐪熺殑蹇級
  • 闇€瑕佸姩鎬佺淮鎶ら€夐殢鏈烘暟姹狅紙铏界劧浠g爜澶氱偣浣嗙伒娲伙級
  • 閲嶈绯荤粺蹇呴』鍋氶噸澶嶅厹搴曟牎楠岋紙鏁版嵁搴撳敮涓€绱㈠紩涓嶈兘鐪侊級

馃 浣犱互涓鸿繖灏卞畬浜嗭紵杩欎簺鍧戣繕鍦ㄧ瓑浣狅紒

  1. 鈥?strong>鈥嬪苟琛屾祦闄烽槺鈥?/strong>鈥嬶細鐢╬arallelStream澶勭悊HashSet浼氬鑷存暟鎹涪澶?/li>
  2. 鈥?strong>鈥嬮殢鏈烘暟绉嶅瓙鈥?/strong>鈥嬶細娴嬭瘯鏃惰缃浐瀹氱瀛愬彲鑳藉紩鍙戠敓浜т簨鏁?/li>
  3. 鈥?strong>鈥嬪璞℃睜娉勯湶鈥?/strong>鈥嬶細蹇樿绉婚櫎宸查€夊厓绱犱細瀵艰嚧鏃犻檺寰幆
  4. 鈥?strong>鈥嬫诞鐐规暟璇樊鈥?/strong>鈥嬶細鐢╠ouble绫诲瀷鍒ゆ柇閲嶅鍙兘缈昏溅

馃殌 鎴戠殑绉佽棌瑙e喅鏂规

鏈€杩戝彂鐜颁釜楠氭搷浣溾€斺€斺€?strong>鈥嬩綅鍥炬硶鈥?/strong>鈥嬶紝閫傚悎瓒呭ぇ鏁版嵁閲忕殑鍦烘櫙銆傛瘮濡傚鐞嗙櫨涓囩骇鎵嬫満鍙峰幓閲嶏細

java澶嶅埗
BitSet bitSet = new BitSet(10_000_000);
Random rand = new Random();

while(count < 10000) {
    int num = rand.nextInt(10_000_000);
    if(!bitSet.get(num)) {
        bitSet.set(num);
        count++;
    }
}

瀹炴祴鐢熸垚鐧句竾涓嶉噸澶嶆暟锛屽唴瀛樺崰鐢ㄤ粠200MB闄嶅埌1.3MB锛佷笉杩囪娉ㄦ剰鏁板瓧鑼冨洿涓嶈兘瓒呰繃BitSet瀹归噺锛岃繖鎷涘睘浜庡吀鍨嬬殑绌洪棿鎹㈡椂闂淬€?/p>

本文由嘻道妙招独家原创,未经允许,严禁转载