අහඹු ඇල්ෆා සංඛ්‍යාත්මක නූලක් ජනනය කරන්නේ කෙසේද?


1750

ව්‍යාජ සසම්භාවී ඇල්ෆා සංඛ්‍යාත්මක නූලක් ජනනය කිරීම සඳහා මම සරල ජාවා ඇල්ගොරිතමයක් සොයමින් සිටියෙමි . මගේ තත්වය තුළ එය 500K+පරම්පරාවට වඩා අද්විතීය විය හැකි අද්විතීය සැසියක් / යතුරු හඳුනාගැනීමක් ලෙස භාවිතා කරනු ඇත (මගේ අවශ්‍යතාවන්ට වඩා නවීන කිසිවක් අවශ්‍ය නොවේ).

ඉතා මැනවින්, මගේ අද්විතීය අවශ්‍යතා අනුව දිගක් නියම කිරීමට මට හැකි වනු ඇත. නිදසුනක් ලෙස, ජනනය කරන ලද දිග 12 දිගට සමාන විය හැකිය "AEYGF7K0DM1X".



59
උපන් දින විරුද්ධාභාසය සැලකිල්ලට ගනිමින්, ඔබ අක්ෂර සංඛ්‍යා 12 ක් (මුළු 62 ක්) භාවිතා කරන්නේ නම්, විරුද්ධාභාසය කරා ළඟා වීමට ඔබට තවමත් නූල් බිලියන 34 කට වඩා අවශ්‍ය වේ. උපන්දින විරුද්ධාභාෂය කෙසේ හෝ ision ට්ටනයක් සහතික නොකරයි, එය පවසන්නේ එය 50% කට වඩා වැඩි අවස්ථාවක් බවයි.
NullUserException

4
UllNullUserException 50% ක සාර්ථක අවස්ථාවක් (උත්සාහයකට) ඉතා ඉහළයි: උත්සාහයන් 10 ක් තිබියදීත්, සාර්ථකත්ව අනුපාතය 0.999 කි. ඒ සමඟම ඔබට පැය 24 ක කාලයක් තුළ බොහෝ දේ අත්හදා බැලිය හැකිය, අවම වශයෙන් එකක් වත් අනුමාන කිරීමට ඔබට විශ්වාස කිරීමට නූල් බිලියන 34 ක් අවශ්‍ය නොවේ. සමහර සැසි ටෝකන සැබවින්ම දිගු විය යුතු හේතුව එයයි.
පිජුස්න්

16
මෙම තනි රේඛා කේත 3 මම අනුමාන කිරීමට බෙහෙවින් ප්‍රයෝජනවත් වේ ..Long.toHexString(Double.doubleToLongBits(Math.random())); UUID.randomUUID().toString(); RandomStringUtils.randomAlphanumeric(12);
මනීන්දර්

19
මම මේ උපන් දිනය විරුද්ධාභාෂය දී "50% අවස්ථාවක්" යනු පැරණි වන අතර, නමුත් ... දැන @Pijusn නොවේ "උත්සාහක අනුව", එය, "නූල් බිලියන 34 (මෙම අවස්ථාවේදී) අතර, දී එහි පවතී, බව 50% ක් අවස්ථාව අවම වශයෙන් අනුපිටපත් යුගලයක් ". ඔබ 1.6 අවශ්ය කියලා සැප්, උත්සාහක දිනුමක් එක් 50% ක අවස්ථාවක් වන පිණිස ඔබගේ දත්ත සමුදාය තුළ ඇතුළත් කිරීම් - 1.6e21 - illion.
ටින් විශාරද

Answers:


1545

ඇල්ගොරිතම

සසම්භාවී නූලක් ජනනය කිරීම සඳහා, පිළිගත හැකි සංකේත සමූහයේ සිට අහඹු ලෙස අඳින ලද අක්ෂර වින්‍යාසය අපේක්ෂිත දිගට ළඟා වන තුරු.

ක්‍රියාත්මක කිරීම

අහඹු හඳුනාගැනීම් ජනනය කිරීම සඳහා තරමක් සරල හා ඉතා නම්‍යශීලී කේතයක් මෙන්න. වැදගත් යෙදුම් සටහන් සඳහා පහත තොරතුරු කියවන්න .

public class RandomString {

    /**
     * Generate a random string.
     */
    public String nextString() {
        for (int idx = 0; idx < buf.length; ++idx)
            buf[idx] = symbols[random.nextInt(symbols.length)];
        return new String(buf);
    }

    public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    public static final String lower = upper.toLowerCase(Locale.ROOT);

    public static final String digits = "0123456789";

    public static final String alphanum = upper + lower + digits;

    private final Random random;

    private final char[] symbols;

    private final char[] buf;

    public RandomString(int length, Random random, String symbols) {
        if (length < 1) throw new IllegalArgumentException();
        if (symbols.length() < 2) throw new IllegalArgumentException();
        this.random = Objects.requireNonNull(random);
        this.symbols = symbols.toCharArray();
        this.buf = new char[length];
    }

    /**
     * Create an alphanumeric string generator.
     */
    public RandomString(int length, Random random) {
        this(length, random, alphanum);
    }

    /**
     * Create an alphanumeric strings from a secure generator.
     */
    public RandomString(int length) {
        this(length, new SecureRandom());
    }

    /**
     * Create session identifiers.
     */
    public RandomString() {
        this(21);
    }

}

භාවිත උදාහරණ

අක්ෂර 8 හඳුනාගැනීම් සඳහා අනාරක්ෂිත ජනක යන්ත්‍රයක් සාදන්න:

RandomString gen = new RandomString(8, ThreadLocalRandom.current());

සැසි හඳුනාගැනීම් සඳහා ආරක්ෂිත ජනක යන්ත්‍රයක් සාදන්න:

RandomString session = new RandomString();

මුද්‍රණය සඳහා පහසුවෙන් කියවිය හැකි කේත සහිත ජනක යන්ත්‍රයක් සාදන්න. අඩු සංකේත භාවිතා කිරීම සඳහා වන්දි ගෙවීම සඳහා නූල් සම්පූර්ණ අක්ෂර සංඛ්‍යා වලට වඩා දිගු වේ:

String easy = RandomString.digits + "ACEFGHJKLMNPQRUVWXYabcdefhijkprstuvwx";
RandomString tickets = new RandomString(23, new SecureRandom(), easy);

සැසි හඳුනාගැනීම් ලෙස භාවිතා කරන්න

අද්විතීය විය හැකි සැසි හඳුනාගැනීම් උත්පාදනය කිරීම ප්‍රමාණවත් නොවේ, නැතහොත් ඔබට සරල කවුන්ටරයක් ​​භාවිතා කළ හැකිය. පුරෝකථනය කළ හැකි හඳුනාගැනීම් භාවිතා කරන විට ප්‍රහාරකයින් සැසි පැහැර ගනී.

දිග සහ ආරක්ෂාව අතර ආතතියක් පවතී. කෙටි හඳුනාගැනීම් අනුමාන කිරීම පහසුය, මන්ද අඩු හැකියාවන් ඇත. නමුත් දිගු හඳුනාගැනීම් මඟින් වැඩි ගබඩා සහ කලාප පළලක් පරිභෝජනය කරයි. විශාල සංකේත සමූහයක් උපකාරී වේ, නමුත් හඳුනාගැනීම් URL වල ඇතුළත් කර ඇත්නම් හෝ අතින් නැවත ඇතුළත් කළහොත් කේතීකරණ ගැටළු ඇති විය හැක.

සැසි හඳුනාගැනීම් සඳහා අහඹු හෝ එන්ට්‍රොපියෙහි මූලික ප්‍රභවය විය යුත්තේ ගුප්ත විද්‍යාව සඳහා නිර්මාණය කර ඇති අහඹු සංඛ්‍යා උත්පාදක ය. කෙසේ වෙතත්, මෙම ජනක යන්ත්‍ර ආරම්භ කිරීම සමහර විට පරිගණකමය වශයෙන් මිල අධික හෝ මන්දගාමී විය හැකි බැවින් හැකි සෑම විටම ඒවා නැවත භාවිතා කිරීමට උත්සාහ කළ යුතුය.

වස්තු හඳුනාගැනීම් ලෙස භාවිතා කරන්න

සෑම යෙදුමකටම ආරක්ෂාව අවශ්‍ය නොවේ. අහඹු පැවරුම කිසිදු සම්බන්ධීකරණයක් හෝ කොටස් කිරීමකින් තොරව හවුල් අවකාශයක හඳුනාගැනීම් උත්පාදනය කිරීම සඳහා බහු ආයතනවලට කාර්යක්ෂම ක්‍රමයක් විය හැකිය. සම්බන්ධීකරණය මන්දගාමී විය හැකිය, විශේෂයෙන් පොකුරු හෝ බෙදා හරින ලද පරිසරයක, සහ අවකාශය බෙදීම ගැටළු ඇති කරන්නේ ආයතන ඉතා කුඩා හෝ විශාල කොටස් සමඟ අවසන් වන විට ය.

බොහෝ වෙබ් යෙදුම්වල සිදු වන පරිදි, ප්‍රහාරකයාට ඒවා බැලීමට හා හැසිරවීමට හැකි නම්, ඒවා අනපේක්ෂිත කිරීමට පියවර නොගෙන ජනනය කරන හඳුනාගැනීම් වෙනත් ක්‍රමවලින් ආරක්ෂා කළ යුතුය. ප්රවේශ අවසරයකින් තොරව ප්රහාරකයාට අනන්‍යතාවය අනුමාන කළ හැකි වස්තූන් ආරක්ෂා කරන වෙනම බලය පැවරීමේ පද්ධතියක් තිබිය යුතුය.

අපේක්ෂිත මුළු හඳුනාගැනීම් සංඛ්‍යාව අනුව ගැටුම් ඇතිවීමට ඉඩක් නොමැති තරම් දිගු හඳුනාගැනීම් භාවිතා කිරීමට ද සැලකිලිමත් විය යුතුය. මෙය "උපන් දින විරුද්ධාභාසය" ලෙස හැඳින්වේ. ගැටීමෙන් සම්භාවිතාව, පි , ආසන්න වශයෙන් n යනු 2 / (2q x එහිදී), n ඇත්තටම ජනනය හඳුනා සංඛ්යාව වන අතර, q හෝඩියේ දී පැහැදිලි සංකේත සංඛ්යාව වන අතර, x යන හඳුනා දිග වේ. මෙය 2 ‑50 හෝ ඊට අඩු ඉතා කුඩා සංඛ්‍යාවක් විය යුතුය .

මෙය ක්‍රියාත්මක කිරීමෙන් පෙනී යන්නේ 500k 15 අක්ෂර හඳුනාගැනීම් අතර ision ට්ටනය වීමේ අවස්ථාව 2 ‑52 ක් පමණ වන අතර එය කොස්මික් කිරණ ආදියෙන් හඳුනා නොගත් දෝෂ වලට වඩා අඩු විය හැකි බවයි.

UUIDs සමඟ සංසන්දනය කිරීම

ඔවුන්ගේ පිරිවිතරයන්ට අනුව, UUIDs අනපේක්ෂිත ලෙස නිර්මාණය කර නොමැති අතර සැසි හඳුනාගැනීම් ලෙස භාවිතා නොකළ යුතුය.

UUIDs ඒවායේ සම්මත ආකෘතියෙන් විශාල ඉඩ ප්‍රමාණයක් ගනී: එන්ට්‍රොපි බිටු 122 ක් සඳහා අක්ෂර 36 ක්. ("අහඹු" UUID හි සියලුම බිටු අහඹු ලෙස තෝරා නොගනී.) අහඹු ලෙස තෝරාගත් අක්ෂරාංක නූලක් අක්ෂර 21 කින් වැඩි එන්ට්‍රොපිය ඇසුරුම් කරයි.

UUIDs නම්යශීලී නොවේ; ඒවාට ප්‍රමිතිගත ව්‍යුහයක් සහ පිරිසැලසුමක් ඇත. මෙය ඔවුන්ගේ ප්‍රධාන ගුණාංගය මෙන්ම ඔවුන්ගේ ප්‍රධාන දුර්වලතාවයයි. බාහිර පාර්ශවයක් සමඟ සහයෝගයෙන් කටයුතු කරන විට, UUIDs ඉදිරිපත් කරන ප්‍රමිතිකරණය ප්‍රයෝජනවත් විය හැකිය. තනිකරම අභ්‍යන්තර භාවිතය සඳහා ඒවා අකාර්යක්ෂම විය හැකිය.


6
ඔබට අවකාශය අවශ්‍ය නම්, රීජෙක්ස් හුවමාරුවක් කිරීමට ඔබට රේඛාවේ .replaceAll("\\d", " ");කෙළවරට සම්බන්ධ විය return new BigInteger(130, random).toString(32);හැකිය. එය සියලු ඉලක්කම් අවකාශයන් සමඟ ප්‍රතිස්ථාපනය කරයි. මට හොඳට වැඩ කරයි: මම මෙය ඉදිරිපස අන්තයේ
ලොරම් ඉප්සම්

4
isweisjohn ඒක හොඳ අදහසක්. ඉලක්කම් ඉවත් කර symbolsඒ වෙනුවට අවකාශයක් භාවිතා කිරීමෙන් ඔබට දෙවන ක්‍රමයට සමාන දෙයක් කළ හැකිය ; සංකේතවල ඇති අවකාශ ගණන වෙනස් කිරීමෙන් ඔබට සාමාන්‍ය "වචන" දිග පාලනය කළ හැකිය (කෙටි වචන සඳහා වැඩි අවස්ථා). සැබවින්ම ඉහළින් ඇති ව්‍යාජ පෙළ විසඳුමක් සඳහා, ඔබට මාකෝව් දාමයක් භාවිතා කළ හැකිය!
එරික්සන්

4
මෙම හඳුනාගැනීම් අහඹු ලෙස තෝරාගෙන ඇත්තේ යම් ප්‍රමාණයක ඉඩ ප්‍රමාණයකිනි. ඒවා අක්ෂර 1 ක් විය හැකිය. ඔබ ස්ථාවර දිග අවශ්ය නම්, ඔබ සමග, දෙවන විසඳුමක් භාවිතා කළ හැකිය SecureRandomපවරන උදාහරණයක් randomවිචල්ය.
එරික්සන්

15
.ToString (36) වෙනුවට .toString (32) ඇයි?
ejain

17
32ejain නිසා 32 = 2 ^ 5; සෑම අක්ෂරයක්ම හරියටම බිටු 5 ක් නියෝජනය කරන අතර බිටු 130 ක් ඒකාකාරව අක්ෂරවලට බෙදිය හැකිය.
එරික්සන්

820

ජාවා මෙය කෙලින්ම කළ හැකි ක්‍රමයක් සපයයි. ඔබට ඉරක් අවශ්‍ය නැතිනම් ඒවා ඉවත් කිරීම පහසුය. භාවිතා කරන්නuuid.replace("-", "")

import java.util.UUID;

public class randomStringGenerator {
    public static void main(String[] args) {
        System.out.println(generateString());
    }

    public static String generateString() {
        String uuid = UUID.randomUUID().toString();
        return "uuid = " + uuid;
    }
}

ප්‍රතිදානය:

uuid = 2d7428a6-b58c-4008-8575-f05549f16316

34
මෙම විසඳුම ජනනය කරන්නේ ෂඩාස්රාකාර අක්ෂර සහිත අහඹු නූලක් පමණක් බව පරෙස්සම් වන්න. සමහර අවස්ථාවල එය හොඳ විය හැකිය.
ඩේව්

5
UUID පන්තිය ප්‍රයෝජනවත් වේ. කෙසේ වෙතත්, ඒවා මගේ පිළිතුරු මගින් නිපදවන හඳුනාගැනීම් තරම් සංයුක්ත නොවේ. මෙය URL වල ගැටලුවක් විය හැකිය. ඔබේ අවශ්‍යතා මත රඳා පවතී.
එරික්සන්

6
Ugs රග්ස් - ඉලක්කය වන්නේ ඇල්ෆා සංඛ්‍යාත්මක නූල් ය. හැකි ඕනෑම බයිට් වලට ප්‍රතිදානය පුළුල් කිරීම එයට ගැලපෙන්නේ කෙසේද?
එරික්සන්

72
RFC4122 ට අනුව UUID ටෝකන ලෙස භාවිතා කිරීම නරක අදහසකි: UUIDs අනුමාන කිරීම දුෂ්කර යැයි නොසිතන්න; නිදසුනක් ලෙස ඒවා ආරක්ෂක හැකියාවන් ලෙස භාවිතා නොකළ යුතුය (හුදෙක් සන්තකයේ ප්‍රවේශය ලබා දෙන හඳුනාගැනීම්). පුරෝකථනය කළ හැකි අහඹු සංඛ්‍යා ප්‍රභවයක් තත්වය තවත් උග්‍ර කරනු ඇත. ietf.org/rfc/rfc4122.txt
සෝමාටික්

35
UUID.randomUUID().toString().replaceAll("-", "");ඉල්ලූ පරිදි නූල් ඇල්ෆා සංඛ්‍යාත්මක කරයි.
Numid

550
static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static SecureRandom rnd = new SecureRandom();

String randomString( int len ){
   StringBuilder sb = new StringBuilder( len );
   for( int i = 0; i < len; i++ ) 
      sb.append( AB.charAt( rnd.nextInt(AB.length()) ) );
   return sb.toString();
}

61
+1, නිශ්චිත දිග අහඹු ලෙස උත්පාදනය කිරීම සඳහා ඇති සරලම විසඳුම (කොමන්ස් ලැන්ග් වෙතින් සසම්භාවී ස්ට්‍රිං යූටිල්ස් භාවිතා කිරීම හැර).
ජොනික්

12
පන්තිය SecureRandomවෙනුවට භාවිතා කිරීම සලකා බලන්න Random. මුරපද සේවාදායකයක් තුළ ජනනය කරන්නේ නම්, එය කාල ප්‍රහාරයන්ට ගොදුරු විය හැකිය.
foens

8
මම කුඩා අකුරු ද එකතු කරමි: AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";සහ තවත් අවසර ලත් අක්ෂර.
ACV

1
static Random rnd = new Random();ක්රමය තුළට දැමිය නොහැක්කේ ඇයි ?
මයික්‍රෝ

4
Ic මයික්‍රෝආර් Randomඑක් එක් ක්‍රමවේදය තුළ වස්තුව නිර්මාණය කිරීමට හොඳ හේතුවක් තිබේද? මම හිතන්නේ නැහැ.
කැසියෝමොලින්

484

ඔබ Apache පන්ති භාවිතා කිරීමට සතුටු නම්, ඔබට org.apache.commons.text.RandomStringGenerator(පොදු-පෙළ) භාවිතා කළ හැකිය .

උදාහරණයක්:

RandomStringGenerator randomStringGenerator =
        new RandomStringGenerator.Builder()
                .withinRange('0', 'z')
                .filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS)
                .build();
randomStringGenerator.generate(12); // toUpperCase() if you want

කොමන්ස්-ලැන්ග් 3.6 සිට RandomStringUtilsඉවත් කර ඇත.


22
සඳහන් කළ Apache Commons Lang 3.3.1පුස්තකාල පන්තිය හරහා දැන් බැලූ බැල්මට - එය භාවිතා java.util.Randomකරන්නේ අහඹු අනුක්‍රමයන් සැපයීම සඳහා පමණි , එබැවින් එය අනාරක්ෂිත අනුක්‍රමයන් නිෂ්පාදනය කරයි.
යූරි නැකොනෙක්නි

16
RandomStringUtils භාවිතා කරන විට ඔබ SecureRandom භාවිතා කරන බවට වග බලා ගන්න:public static java.lang.String random(int count, int start, int end, boolean letters, boolean numbers, @Nullable char[] chars, java.util.Random random)
Ruslans Uralovs

පාවිච්චි කරන්න එපා. මෙය අනාරක්ෂිත අනුපිළිවෙලක් නිර්මාණය කරයි !
පැට්‍රික් ෆාවර්

111

මේ සඳහා ඔබට Apache පුස්තකාලය භාවිතා කළ හැකිය: RandomStringUtils

RandomStringUtils.randomAlphanumeric(20).toUpperCase();

18
amkamil, මම RandomStringUtils සඳහා වන ප්‍රභව කේතය දෙස බැලුවෙමි, එය java.util හි උදාහරණයක් භාවිතා කරයි. Java.util.Random සඳහා වන ලියකියවිලි පවසන්නේ බීජ ලබා නොදුනහොත් එය වත්මන් පද්ධති කාලය භාවිතා කරන බවයි. මෙයින් අදහස් කරන්නේ ඕනෑම වේලාවක ජනනය කරන ලද සැසි හඳුනාගැනීම් මොනවාදැයි ප්‍රහාරකයාට පහසුවෙන් පුරෝකථනය කළ හැකි බැවින් එය සැසි හඳුනාගැනීම් / යතුරු සඳහා භාවිතා කළ නොහැකි බවයි.
ඉන්ෂල්ලා

36
Ins ඉන්ෂල්ලා: ඔබ (අනවශ්‍ය ලෙස) පද්ධතිය ඉක්මවා යයි. එය බීජ ලෙස කාලය භාවිතා කරන බව මා එකඟ වන අතර, ප්‍රහාරකයාට තමාට අවශ්‍ය දේ ලබා ගැනීම සඳහා පහත සඳහන් දත්ත වලට ප්‍රවේශය තිබිය යුතුය 1. කේතය බීජ කළ විට හරියටම මිලි තත්පරයට වේලාව 2. මෙතෙක් සිදු වූ ඇමතුම් ගණන 3. ඔහුගේම ඇමතුම සඳහා පරමාණුකතාව (එම නිසා මෙතෙක් ලැබී ඇති ඇමතුම් ගණන එක හා සමානයි) ඔබේ ප්‍රහාරකයාට මේ කාරණා තුනම තිබේ නම්, ඔබට වඩා විශාල ප්‍රශ්නයක් තිබේ ...
අජීත් ගංගා

3
gradle යැපීම: compile 'commons-lang:commons-lang:2.6'
younes0

4
J අජිත් මෙය සත්‍ය නොවේ. සසම්භාවී සංඛ්‍යා උත්පාදක යන්ත්රයේ තත්වය ඔබට එහි නිමැවුමෙන් ලබා ගත හැකිය. අහඹු API ටෝකන ජනනය කිරීම සඳහා ප්‍රහාරකයාට ඇමතුම් දහස් ගණනක් උත්පාදනය කළ හැකි නම්, අනාගත API ටෝකන සියල්ල පුරෝකථනය කිරීමට ප්‍රහාරකයාට හැකි වේ.
තෝමස් ග්‍රේන්ජර්

3
J අජිත්ගංග ඉංජිනේරු විද්‍යාව හා සම්බන්ධ කිසිවක් නැත. ඔබට සැසි හැඳුනුම්පත් සෑදීමට අවශ්‍ය නම්, ඔබට ගුප්ත ලේඛන ව්‍යාජ සසම්භාවී උත්පාදකයක් අවශ්‍ය වේ. සෑම බීජයක්ම බීජ ලෙස කාලය භාවිතා කිරීම අනාවැකි කිව හැකි සහ අනපේක්ෂිත විය යුතු දත්ත සඳහා ඉතා අනාරක්ෂිත ය. භාවිතා කරන්න SecureRandom, ඔබ හොඳයි.
පැට්‍රික් ෆාවර්

105

එක් පේළියක:

Long.toHexString(Double.doubleToLongBits(Math.random()));

http://mynotes.wordpress.com/2009/07/23/java-generating-random-string/


9
නමුත් අකුරු 6 ක් පමණි :(
මෝෂේ රේවා

2
එය මටද උදව් කළ නමුත්
ෂඩාස්රාකාර

Ipp සිපොක්සර්, ඔබට කිහිප වතාවක්ම එකඟ විය හැකිය =)
daniel.bavrin

7
OP හි උදාහරණයෙන් පහත දැක්වෙන නූල් ෂඩාස්රාකාර නොවන උදාහරණයක් ලෙස පෙන්වන ලදී AEYGF7K0DM1X. මිනිසුන් හෙක්සැඩිසිමල් සමඟ අක්ෂර සංඛ්‍යා වැරදි කරන්නේ කොපමණ වාරයක් දැයි මට කණගාටුයි. ඒවා එකම දෙයක් නොවේ.
hfontanez

6
මෙය 0 සිට 1 දක්වා ප්‍රමාණයක් Math.random()නිපදවන පරිදි නූල් දිග ලබා දිය යුතු ප්‍රමාණයට වඩා අඩු අහඹු වේ double, එබැවින් on ාතීය කොටස බොහෝ විට භාවිතා නොවේ. මෙම කැත හැක් වෙනුවට random.nextLongඅහඹු ලෙස භාවිතා කරන්න long.
maaartinus

81

බාහිර පුස්තකාල නොමැතිව මෙය පහසුවෙන් ළඟා කර ගත හැකිය.

1. ගුප්ත ලේඛන ව්‍යාජ සසම්භාවී දත්ත උත්පාදනය

පළමුව ඔබට ගුප්ත ලේඛනගත PRNG අවශ්‍ය වේ. ජාවා ඒ SecureRandomසඳහා ඇති අතර සාමාන්‍යයෙන් යන්ත්‍රයේ හොඳම එන්ට්‍රොපි ප්‍රභවය භාවිතා කරයි (උදා /dev/random). වැඩි විස්තර මෙතැනින් කියවන්න.

SecureRandom rnd = new SecureRandom();
byte[] token = new byte[byteLength];
rnd.nextBytes(token);

සටහන: SecureRandom අහඹු බයිට් ජනනය කිරීමේ ජාවාහි මන්දගාමී, නමුත් වඩාත්ම ආරක්ෂිත ක්‍රමයයි. කෙසේවෙතත්, තත්පරයට ටෝකන මිලියන ගණනක් උත්පාදනය කළ යුතු නම් මිස, සාමාන්‍යයෙන් ඔබේ යෙදුමට එය සැබෑ බලපෑමක් නොකරන බැවින් මෙහි ක්‍රියාකාරිත්වය සලකා නොබලන ලෙස මම නිර්දේශ කරමි.

2. විය හැකි වටිනාකම් සඳහා අවශ්‍ය අවකාශය

ඊළඟට ඔබේ ටෝකනය "කෙතරම් අද්විතීයද" යන්න තීරණය කළ යුතුය. හැකි වටිනාකම් අවකාශය ඕනෑම ප්රහාරකයා එකම හාස්යජනක නොවන කාලයක් තුළ වටිනාකම් නොසැලකිය යුතු ප්රතිශතය උත්සාහ හැකි වන පරිදි විශාල විය යුතුය: සලකා එන්ට්රොපියේ මුළු සහ එකම අවස්ථාවක වග බලා ගන්න ක්රමයක් ෆෝස් පහර දෙනවිට හැකි බව බවට පත් කිරීම 1 . සසම්භාවී වැනි අද්විතීය හඳුනාගැනීම් වලට UUIDඑන්ට්‍රොපිය 122bit (එනම් 2 ^ 122 = 5.3x10 ^ 36) ඇත - ision ට්ටනය වීමේ අවස්ථාව "* (...) සඳහා අනුපිටපත් බිලියනයක එකක්, ට්‍රිලියන 103 අනුවාදය UUIDs 4 ජනනය කළ යුතුය 2 ". අපි බිට් 128 ක් තෝරා ගන්නේ එය හරියටම බයිට් 16 කට ගැලපෙන නිසා සහ එය ප්‍රමාණවත් තරම් පෙනෙන බැවිනිමූලික වශයෙන් සෑම කෙනෙකුටම අද්විතීය වීම සඳහා, නමුත් වඩාත්ම ආන්තික, අවස්ථා භාවිතා කරන්න, ඔබ අනුපිටපත් ගැන සිතිය යුතු නැත. උපන් දින ගැටලුව පිළිබඳ සරල විශ්ලේෂණයක් ඇතුළුව එන්ට්‍රොපිය පිළිබඳ සරල සංසන්දනාත්මක වගුවක් මෙන්න .

ටෝකන ප්‍රමාණ සංසන්දනය කිරීම

සරල අවශ්‍යතා සඳහා බයිට් 8 ක් හෝ 12 ක් ප්‍රමාණවත් විය හැකි නමුත් බයිට් 16 ක් සමඟ ඔබ සිටින්නේ “ආරක්ෂිත පැත්තේ” ය.

එය මූලික වශයෙන් එයයි. අවසාන දෙය නම් කේතනය කිරීම ගැන සිතීමයි, එවිට එය මුද්‍රණය කළ හැකි පෙළක් ලෙස දැක්විය හැකිය (කියවන්න, අ String).

3. ද්විමය සිට පෙළ කේතීකරණය

සාමාන්‍ය කේතන ක්‍රමවලට ඇතුළත් වන්නේ:

  • Base64සෑම අක්‍ෂරයක්ම 6bit සංකේතවත් කරන්නේ 33% ක ඉහළින්. වාසනාවකට ජාවා 8+ සහ ඇන්ඩ්‍රොයිඩ් වල සම්මත ක්‍රියාත්මක කිරීම් තිබේ . පැරණි ජාවා සමඟ ඔබට ඕනෑම තෙවන පාර්ශවීය පුස්තකාල භාවිතා කළ හැකිය . ඔබේ ටෝකන url ආරක්ෂිත වීමට ඔබට අවශ්‍ය නම් RFC4648 හි url- ආරක්ෂිත අනුවාදය භාවිතා කරන්න (සාමාන්‍යයෙන් බොහෝ ක්‍රියාත්මක කිරීම් සඳහා එය සහාය වේ). පෑඩින් සමඟ බයිට් 16 ක් කේතනය කිරීමේ උදාහරණ:XfJhfv3C0P6ag7y9VQxSbw==

  • Base32සෑම අක්‍ෂරයක්ම 5bit සංකේතවත් කරන්නේ 40% ක ඉහළින්. මෙම භාවිතා කරනු ඇත A-Zසහ 2-7නඩුව-අසංවේදී ඇල්ෆා-සංඛ්යාත්මක වීම අතර එය සාදාරණ අවකාශය කාර්යක්ෂම කිරීම. JDK හි සම්මත ක්‍රියාත්මක කිරීමක් නොමැත . පෑඩ් කිරීමකින් තොරව බයිට් 16 ක් කේතනය කිරීමේ උදාහරණය:WUPIL5DQTZGMF4D3NX5L7LNFOY

  • Base16(හෙක්ස්) සෑම අක්ෂරයක්ම 4bit සංකේතවත් කරන්නේ බයිට් එකකට අක්ෂර 2 ක් අවශ්‍ය වේ (එනම් 16 බයිට් දිග 32 ක නූලක් සාදයි). ඒ නිසා ඔබ hex වඩා කාර්යක්ෂම අඩු ඉඩක් වේ Base32නමුත් එය පමණක් භාවිතා සිට බොහෝ අවස්ථාවල (url එක) භාවිතා කිරීම ආරක්ෂාකාරී වන 0-9අතර Aගැනීමට F. උදාහරණ බයිට් 16 කේතනය කිරීම : 4fa3dd0f57cb3bf331441ed285b27735. හෙක්ස් බවට පරිවර්තනය කිරීම පිළිබඳ SO සාකච්ඡාවක් මෙතැනින් බලන්න.

Base85 සහ විදේශීය Base122 වැනි අතිරේක කේතීකරණ වඩා හොඳ / නරක අභ්‍යවකාශ කාර්යක්ෂමතාවයකින් පවතී. ඔබට ඔබේම කේතීකරණයක් සෑදිය හැකිය (මූලික වශයෙන් මෙම ත්‍රෙඩ් එකේ බොහෝ පිළිතුරු සපයන) නමුත් ඔබට නිශ්චිත අවශ්‍යතා නොමැති නම් මම එයට එරෙහිව උපදෙස් දෙමි. විකිපීඩියා ලිපියේ තවත් කේතීකරණ යෝජනා ක්‍රම බලන්න .

4. සාරාංශය සහ උදාහරණය

  • භාවිත SecureRandom
  • හැකි අගයන්ගෙන් අවම වශයෙන් බයිට් 16 ක් (2 ^ 128) භාවිතා කරන්න
  • ඔබගේ අවශ්‍යතා අනුව එන්කෝඩ් කරන්න (සාමාන්‍යයෙන් hexහෝ base32ඔබට එය ඇල්ෆා සංඛ්‍යාත්මක වීමට අවශ්‍ය නම්)

එපා

  • ... ඔබේ නිවසේ බීර කේතන ක්‍රමය භාවිතා කරන්න: වරකට අක්ෂර නිර්මාණය කරන ලූප සඳහා අමුතු වෙනුවට ඔබ භාවිතා කරන සම්මත කේතන ක්‍රමය අන් අයට පෙනේ නම් වඩා හොඳ නඩත්තු කළ හැකි සහ කියවිය හැකි ය.
  • ... UUID භාවිතා කරන්න: එයට අහඹු බව පිළිබඳ සහතිකයක් නොමැත; ඔබ එන්ට්‍රොපි 6bit නාස්ති කරන අතර වාචික නූල් නිරූපණය ඇත

උදාහරණය: හෙක්ස් ටෝකන් උත්පාදක යන්ත්රය

public static String generateRandomHexToken(int byteLength) {
    SecureRandom secureRandom = new SecureRandom();
    byte[] token = new byte[byteLength];
    secureRandom.nextBytes(token);
    return new BigInteger(1, token).toString(16); //hex encoding
}

//generateRandomHexToken(16) -> 2189df7475e96aa3982dbeab266497cd

උදාහරණය: Base64 ටෝකන් උත්පාදක යන්ත්රය (Url Safe)

public static String generateRandomBase64Token(int byteLength) {
    SecureRandom secureRandom = new SecureRandom();
    byte[] token = new byte[byteLength];
    secureRandom.nextBytes(token);
    return Base64.getUrlEncoder().withoutPadding().encodeToString(token); //base64 encoding
}

//generateRandomBase64Token(16) -> EEcCCAYuUcQk7IuzdaPzrg

උදාහරණය: ජාවා සීඑල්අයි මෙවලම

ඔබට භාවිතා කිරීමට සූදානම් ක්ලයි මෙවලමක් අවශ්‍ය නම් ඔබට ඩයිස් භාවිතා කළ හැකිය: https://github.com/patrickfav/dice

උදාහරණය: අදාළ ගැටළුව - ඔබගේ වර්තමාන අයිඩී ආරක්ෂා කරන්න

ඔබට දැනටමත් භාවිතා කළ හැකි හැඳුනුම්පතක් තිබේ නම් (උදා: longඔබේ ආයතනයේ කෘතිම ), නමුත් අභ්‍යන්තර අගය ප්‍රකාශයට පත් කිරීමට අවශ්‍ය නැතිනම් , ඔබට මෙම පුස්තකාලය සංකේතනය කර එය අපැහැදිලි කිරීමට භාවිතා කළ හැකිය: https://github.com/patrickfav / id-mask

IdMask<Long> idMask = IdMasks.forLongIds(Config.builder(key).build());
String maskedId = idMask.mask(id);
//example: NPSBolhMyabUBdTyanrbqT8
long originalId = idMask.unmask(maskedId);

3
මෙම පිළිතුර සම්පුර්ණ වන අතර කිසිදු යැපීමක් එකතු නොකර ක්‍රියා කරයි. නිමැවුමේ ඇති විය හැකි us ණ සං signs ා වළක්වා ගැනීමට ඔබට අවශ්‍ය නම්, ඔබට BigIntegerඉදිකිරීම් පරාමිතියක් භාවිතා කරමින් negative ණාත්මක s වලක්වා ගත හැකිය : BigInteger(1, token)ඒ වෙනුවට BigInteger(token).
francoisr

ඉඟිය සඳහා ටැංකි ran ෆ්‍රැන්කොයිසර්, මම කේත උදාහරණය සංස්කරණය කළෙමි
පැට්‍රික් ෆාවර්

import java.security.SecureRandom;සහ import java.math.BigInteger;ආදර්ශය ක්‍රියාත්මක කිරීමට අවශ්‍ය නමුත් එය විශිෂ්ට ලෙස ක්‍රියා කරයි!
anothermh

හොඳ පිළිතුරක් / / dev / random යනු අවහිර කිරීමේ ක්‍රමයක් වන අතර එන්ට්‍රොපිය අඩු නම් එය අවහිර වීමේ වේගය මන්දගාමී වේ. වඩා හොඳ සහ අවහිර නොකරන ක්‍රමය වන්නේ / dev / urandom ය. මෙය <jre> /lib/security/java.security හරහා වින්‍යාසගත කළ හැකි අතර saferandom.source = file: / dev /./ urandom
Muzammil

UzMuzammil tersesystems.com/blog/2015/12/17/… බලන්න ( පිළිතුරට ද සම්බන්ධයි) - new SecureRandom()භාවිතා කරයි/dev/urandom
පැට්‍රික් ෆාවර්

42

ඩොලරය භාවිතා කිරීම සරල විය යුතුය:

// "0123456789" + "ABCDE...Z"
String validCharacters = $('0', '9').join() + $('A', 'Z').join();

String randomString(int length) {
    return $(validCharacters).shuffle().slice(length).toString();
}

@Test
public void buildFiveRandomStrings() {
    for (int i : $(5)) {
        System.out.println(randomString(12));
    }
}

එය එවැනි දෙයක් ප්‍රතිදානය කරයි:

DKL1SBH9UJWC
JH7P0IT21EA5
5DTI72EO6SFU
HQUMJTEBNF7Y
1HCR6SKYWGT7

ෂෆල් සමඟ SecureRandom භාවිතා කළ හැකිද?
iwein

34

මෙන්න එය ජාවා හි ඇත:

import static java.lang.Math.round;
import static java.lang.Math.random;
import static java.lang.Math.pow;
import static java.lang.Math.abs;
import static java.lang.Math.min;
import static org.apache.commons.lang.StringUtils.leftPad

public class RandomAlphaNum {
  public static String gen(int length) {
    StringBuffer sb = new StringBuffer();
    for (int i = length; i > 0; i -= 12) {
      int n = min(12, abs(i));
      sb.append(leftPad(Long.toString(round(random() * pow(36, n)), 36), n, '0'));
    }
    return sb.toString();
  }
}

මෙන්න නියැදි ධාවනය:

scala> RandomAlphaNum.gen(42)
res3: java.lang.String = uja6snx21bswf9t89s00bxssu8g6qlu16ffzqaxxoy

4
මෙය අනාරක්ෂිත අනුක්‍රමයන් නිපදවනු ඇත, එනම් පහසුවෙන් අනුමාන කළ හැකි අනුක්‍රමයන්.
යූරි නැකොනෙක්නි

8
මෙම ද්විත්ව ආසාදිත සසම්භාවී int පරම්පරාව සැලසුම්, මන්දගාමී හා කියවිය නොහැකි ලෙස කැඩී ඇත. භාවිතා කරන්න Random#nextIntහෝ nextLong. SecureRandomඅවශ්‍ය නම් මාරු වන්න .
maaartinus

31

කෙටි හා පහසු විසඳුමක්, නමුත් කුඩා අකුරු සහ සංඛ්‍යා පමණක් භාවිතා කරයි:

Random r = new java.util.Random ();
String s = Long.toString (r.nextLong () & Long.MAX_VALUE, 36);

36 වන පාදයට විශාලත්වය ඉලක්කම් 12 ක් පමණ වන අතර එය තවදුරටත් දියුණු කළ නොහැක. ඇත්ත වශයෙන්ම ඔබට අවස්ථා කිහිපයක් එකතු කළ හැකිය.


11
මතක තබා ගන්න, ප්‍රති result ලයට sign ණ ලකුණක් ලබා ගැනීමට 50% ක අවස්ථාවක් ඇති බව! ඔබට Long.toString(Math.abs(r.nextLong()), 36);
r ණ

5
AyRayHulha: ඔබට us ණ ලකුණ අවශ්‍ය නොවන්නේ නම්, ඔබ එය කපා දැමිය යුතුය, මන්ද, පුදුමයට කරුණක් නම්, Math.abs Long.MIN_VALUE සඳහා negative ණ අගයක් ලබා දෙයි.
පරිශීලක නොදන්නා

Math.abs .ණාත්මකව නැවත පැමිණීම සිත්ගන්නා කරුණකි. වැඩි විස්තර මෙතැනින්: bmaurer.blogspot.co.nz/2006/10/…
ෆිල්

1
සමග මෙම ප්රශ්නය absඉතා වැදගත් ටිකක් පැහැදිලි කිරීමට bitwise ක්රියාකරු භාවිතා විසඳා ඇත. මෙය සියලු අගයන් සඳහා ක්‍රියා කරනු ඇත.
රේඩියෝඩෙෆ්

1
@ රේඩියෝඩෙෆ් එය අත්‍යවශ්‍යයෙන්ම @userunkown කීවේය. ඔබටත් කළ හැකි යැයි මම සිතමි << 1 >>> 1.
shmosel

30

පුදුමයට කරුණක් නම් මෙහි කිසිවෙකු එය යෝජනා කර නැති නමුත්:

import java.util.UUID

UUID.randomUUID().toString();

පහසු.

මෙහි වාසිය වන්නේ UUIDs ලස්සන හා දිගු වන අතර ගැටීමට නොහැකි තරම් සහතික වීමයි.

විකිපීඩියාවට ඒ පිළිබඳ හොඳ පැහැදිලි කිරීමක් ඇත:

"... ඉදිරි වසර 100 සඳහා සෑම තත්පරයකම UUID බිලියනයක් ජනනය කිරීමෙන් පසුව පමණක්, එක් අනුපිටපතක් පමණක් නිර්මාණය කිරීමේ සම්භාවිතාව 50% ක් පමණ වනු ඇත."

http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates

පළමු බිටු 4 යනු අනුවාදයේ වර්ගය සහ 2 ප්‍රභේදය සඳහා වන බැවින් ඔබට අහඹු ලෙස බිටු 122 ක් ලැබේ. එබැවින් ඔබට අවශ්‍ය නම් UUID ප්‍රමාණය අඩු කිරීම සඳහා අවසානයේ සිට කපා දැමිය හැකිය. එය නිර්දේශ කර නැති නමුත් ඔබට තවමත් අහඹු ලෙස බරක් ඇත, ඔබගේ 500k වාර්තා සඳහා පහසුය.


41
කවුරුහරි එය යෝජනා කළා, ඔබට අවුරුද්දකට පමණ පෙර.
එරික්සන්

15

ජාවා 8 හි විකල්පයක් වන්නේ:

static final Random random = new Random(); // Or SecureRandom
static final int startChar = (int) '!';
static final int endChar = (int) '~';

static String randomString(final int maxLength) {
  final int length = random.nextInt(maxLength + 1);
  return random.ints(length, startChar, endChar + 1)
        .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
        .toString();
}

3
එය විශිෂ්ටයි - නමුත් ඔබට එය තදින් අක්ෂර සංඛ්‍යා (0-9, az, AZ) ලෙස තබා ගැනීමට අවශ්‍ය නම් මෙහි බලන්න rationaljava.com/2015/06/…
Dan

12

UUIDs භාවිතා කිරීම අනාරක්ෂිත ය, මන්ද UUID හි සමහර කොටස් අහඹු ලෙස නොපවතින බැවිනි. එරික්සන්ගේ ක්‍රියා පටිපාටිය ඉතා පිළිවෙලට ඇති නමුත් එකම දිගකින් යුත් නූල් සාදන්නේ නැත. පහත දැක්වෙන කොටස ප්‍රමාණවත් විය යුතුය:

/*
 * The random generator used by this class to create random keys.
 * In a holder class to defer initialization until needed.
 */
private static class RandomHolder {
    static final Random random = new SecureRandom();
    public static String randomKey(int length) {
        return String.format("%"+length+"s", new BigInteger(length*5/*base 32,2^5*/, random)
            .toString(32)).replace('\u0020', '0');
    }
}

තෝරා ගැනීම ඇයි length*5. අහඹු දිග 1 ක සරල නඩුව උපකල්පනය කරමු, එබැවින් එක් අහඹු අක්ෂරයක්. සියලු ඉලක්කම් 0-9 සහ අක්ෂර az අඩංගු අහඹු අක්‍ෂරයක් ලබා ගැනීම සඳහා, එක් එක් අක්ෂරවලින් එකක් ලබා ගැනීමට අපට 0 සහ 35 අතර අහඹු අංකයක් අවශ්‍ය වේ. BigIntegerපරාසය පුරා ඒකාකාරව බෙදා හරින අහඹු අංකයක් ජනනය කිරීම සඳහා ඉදිකිරීම්කරුවෙකු සපයයි 0 to (2^numBits - 1). අවාසනාවකට 35 යනු 2 ^ numBits - 1. ලබා ගත හැකි අංකයක් නොවේ. එබැවින් අපට විකල්ප දෙකක් තිබේ: එක්කෝ යන්න 2^5-1=31හෝ යන්න 2^6-1=63. අප තෝරා ගන්නේ නම් අපට 2^6"අනවශ්‍ය" / "දිගු" අංක රාශියක් ලැබෙනු ඇත. එබැවින් 2^5අපි අක්ෂර 4 ක් (wz) ලිහිල් කළත් වඩා හොඳ විකල්පය එයයි. දැන් නිශ්චිත දිගකින් යුත් නූලක් ජනනය කිරීමට, අපට සරලවම a භාවිතා කළ හැකිය2^(length*numBits)-1අංකය. අන්තිම ගැටළුව, අපට නිශ්චිත දිගක් සහිත නූලක් අවශ්‍ය නම්, අහඹු ලෙස කුඩා සංඛ්‍යාවක් ජනනය කළ හැකිය, එබැවින් දිග සපුරා නැත, එබැවින් අපට අවශ්‍ය දිගට පෙර ශුන්‍යයට අවශ්‍ය නූල් පටිය කළ යුතුය.


ඔබට 5 වඩා හොඳින් පැහැදිලි කළ හැකිද?
ජූලියන් සුවාරෙස්

11
public static String generateSessionKey(int length){
String alphabet = 
        new String("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); //9
int n = alphabet.length(); //10

String result = new String(); 
Random r = new Random(); //11

for (int i=0; i<length; i++) //12
    result = result + alphabet.charAt(r.nextInt(n)); //13

return result;
}

10
import java.util.Random;

public class passGen{
    //Verison 1.0
    private static final String dCase = "abcdefghijklmnopqrstuvwxyz";
    private static final String uCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String sChar = "!@#$%^&*";
    private static final String intChar = "0123456789";
    private static Random r = new Random();
    private static String pass = "";

    public static void main (String[] args) {
        System.out.println ("Generating pass...");
        while (pass.length () != 16){
            int rPick = r.nextInt(4);
            if (rPick == 0){
                int spot = r.nextInt(25);
                pass += dCase.charAt(spot);
            } else if (rPick == 1) {
                int spot = r.nextInt (25);
                pass += uCase.charAt(spot);
            } else if (rPick == 2) {
                int spot = r.nextInt (7);
                pass += sChar.charAt(spot);
            } else if (rPick == 3){
                int spot = r.nextInt (9);
                pass += intChar.charAt (spot);
            }
        }
        System.out.println ("Generated Pass: " + pass);
    }
}

ඉතින් මෙය කරන්නේ මුරපදය නූලට එක් කිරීම පමණයි ... ඔව්, එය හොඳින් පරීක්ෂා කර බලන්න ... ඉතා සරලයි. මම ඒක ලිව්වා


සුළු වෙනස් කිරීම් කිරීමට මට ඉඩ දුන්නා. ඔබ + 0එය නිතර එකතු කරන්නේ ඇයි? ඔබ ස්ථාන ප්‍රකාශය සහ ආරම්භක ප්‍රකාශනය බෙදන්නේ ඇයි? 0,1,2,3 වෙනුවට 1,2,3,4 දර්ශකවල වාසිය කුමක්ද? වැදගත්ම දෙය: ඔබ අහඹු අගයක් ගත් අතර, වඩා අහඹු ලෙස ලබා නොගෙන සෑම විටම නොගැලපෙන නව අගයක් 4 ගුණයක් සමඟ සසඳන විට. නමුත් ආපසු හැරවීමට නිදහස් වන්න.
පරිශීලකයා නොදන්නා

8

අහඹු හෙක්ස් කේතනය කරන ලද නූලක් ජනනය කරන මෙම විසඳුම මට හමු විය. සපයා ඇති ඒකක පරීක්ෂණය මගේ ප්‍රාථමික භාවිත නඩුව දක්වා ඇති බව පෙනේ. කෙසේ වෙතත්, එය ලබා දී ඇති වෙනත් පිළිතුරු වලට වඩා තරමක් සංකීර්ණ ය.

/**
 * Generate a random hex encoded string token of the specified length
 *  
 * @param length
 * @return random hex string
 */
public static synchronized String generateUniqueToken(Integer length){ 
    byte random[] = new byte[length];
    Random randomGenerator = new Random();
    StringBuffer buffer = new StringBuffer();

    randomGenerator.nextBytes(random);

    for (int j = 0; j < random.length; j++) {
        byte b1 = (byte) ((random[j] & 0xf0) >> 4);
        byte b2 = (byte) (random[j] & 0x0f);
        if (b1 < 10)
            buffer.append((char) ('0' + b1));
        else
            buffer.append((char) ('A' + (b1 - 10)));
        if (b2 < 10)
            buffer.append((char) ('0' + b2));
        else
            buffer.append((char) ('A' + (b2 - 10)));
    }
    return (buffer.toString());
}

@Test
public void testGenerateUniqueToken(){
    Set set = new HashSet();
    String token = null;
    int size = 16;

    /* Seems like we should be able to generate 500K tokens 
     * without a duplicate 
     */
    for (int i=0; i<500000; i++){
        token = Utility.generateUniqueToken(size);

        if (token.length() != size * 2){
            fail("Incorrect length");
        } else if (set.contains(token)) {
            fail("Duplicate token generated");
        } else{
            set.add(token);
        }
    }
}

තනිකරම සම්භාවිතාව මත පදනම් වූ අනුපිටපත් ටෝකන සඳහා අසමත් වීම සාධාරණ යැයි මම නොසිතමි.
Thom Wiggers

8
  1. ඔබේ අවශ්‍යතාවය අනුව සංගීත අක්ෂර වෙනස් කරන්න.

  2. නූල් වෙනස් නොවේ. මෙන්න StringBuilder.appendනූල් සම්මුතියට වඩා කාර්යක්ෂම වේ.


public static String getRandomString(int length) {
       final String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_+";
       StringBuilder result = new StringBuilder();
       while(length > 0) {
           Random rand = new Random();
           result.append(characters.charAt(rand.nextInt(characters.length())));
           length--;
       }
       return result.toString();
    }

3
මීට පෙර ලබා දී ඇති පිළිතුරු දුසිම් ගණනක් ආවරණය නොකිරීමට මෙය කිසිවක් එකතු නොකරයි. තවද Randomලූපයේ එක් එක් නැවතීමේ ක්‍රියාවලියේදී නව අවස්ථාවක් නිර්මාණය කිරීම අකාර්යක්ෂම වේ.
එරික්සන්

7
import java.util.Date;
import java.util.Random;

public class RandomGenerator {

  private static Random random = new Random((new Date()).getTime());

    public static String generateRandomString(int length) {
      char[] values = {'a','b','c','d','e','f','g','h','i','j',
               'k','l','m','n','o','p','q','r','s','t',
               'u','v','w','x','y','z','0','1','2','3',
               '4','5','6','7','8','9'};

      String out = "";

      for (int i=0;i<length;i++) {
          int idx=random.nextInt(values.length);
          out += values[idx];
      }
      return out;
    }
}

7
import java.util.*;
import javax.swing.*;
public class alphanumeric{
    public static void main(String args[]){
        String nval,lenval;
        int n,len;

        nval=JOptionPane.showInputDialog("Enter number of codes you require : ");
        n=Integer.parseInt(nval);

        lenval=JOptionPane.showInputDialog("Enter code length you require : ");
        len=Integer.parseInt(lenval);

        find(n,len);

    }
    public static void find(int n,int length) {
        String str1="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        StringBuilder sb=new StringBuilder(length);
        Random r = new Random();

        System.out.println("\n\t Unique codes are \n\n");
        for(int i=0;i<n;i++){
            for(int j=0;j<length;j++){
                sb.append(str1.charAt(r.nextInt(str1.length())));
            }
            System.out.println("  "+sb.toString());
            sb.delete(0,length);
        }
    }
}

7

"සරල" විසඳුම සම්බන්ධයෙන් මෙම පිළිතුරු කිසිවක් සැබවින්ම කැමති නැත: එස්

මම සරල;), පිරිසිදු ජාවා, එක් ලයිනර් (එන්ට්‍රොපිය පදනම් වන්නේ අහඹු නූල් දිග සහ දී ඇති අක්ෂර කට්ටලය මත ය):

public String randomString(int length, String characterSet) {
    return IntStream.range(0, length).map(i -> new SecureRandom().nextInt(characterSet.length())).mapToObj(randomInt -> characterSet.substring(randomInt, randomInt + 1)).collect(Collectors.joining());
}

@Test
public void buildFiveRandomStrings() {
    for (int q = 0; q < 5; q++) {
        System.out.println(randomString(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"));//charachterSet can basically be anything
    }
}

හෝ (තව ටිකක් කියවිය හැකි පැරණි ක්‍රමය)

public String randomString(int length, String characterSet) {
    StringBuilder sb = new StringBuilder(); //consider using StringBuffer if needed
    for (int i = 0; i < length; i++) {
        int randomInt = new SecureRandom().nextInt(characterSet.length());
        sb.append(characterSet.substring(randomInt, randomInt + 1));
    }
    return sb.toString();
}

@Test
public void buildFiveRandomStrings() {
    for (int q = 0; q < 5; q++) {
        System.out.println(randomString(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")); //charachterSet can basically be anything
    }
}

නමුත් අනෙක් අතට ඔබට හොඳ එන්ට්‍රොපියක් ඇති UUID සමඟද යා හැකිය ( https://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions ):

UUID.randomUUID().toString().replace("-", "")

උපකාරවත් වන බලාපොරොත්තුව.


6

ඔබ "සරල" යැයි සඳහන් කරයි, නමුත් වෙනත් අයෙකු වඩා දැඩි ආරක්ෂක අවශ්‍යතා සපුරාලන යමක් සොයන්නේ නම්, ඔබට jpwgen දෙස බැලීමට අවශ්‍ය විය හැකිය . jpwgen ආදර්ශයට ගෙන ඇත්තේ pwgen යුනික්ස්, සහ ඉතා මානකල වේ.


ස්තූතියි, එය සවි කර ඇත. එබැවින් අවම වශයෙන් ප්‍රභවයක් ඇති අතර සබැඳිය වලංගු වේ. අවාසිය නම්, එය ටික කලකින් යාවත්කාලීන වී ඇති බවක් නොපෙනේ, නමුත් pwgen මෑතකදී යාවත්කාලීන කර ඇති බව මට පෙනේ.
මයිකල්

4

සසම්භාවී දත්ත 64bit ලබා ගැනීම සඳහා ඔබට UUID පන්තිය එහි getLeastSignificantBits () පණිවිඩය භාවිතා කළ හැකිය, පසුව එය රැඩික්ස් 36 අංකයක් බවට පරිවර්තනය කරන්න (එනම් 0-9, AZ වලින් සමන්විත නූලක්):

Long.toString(Math.abs( UUID.randomUUID().getLeastSignificantBits(), 36));

මෙය අක්ෂර 13 ක් දක්වා දිගකින් යුක්ත වේ. In ණ ලකුණක් සොරකම් නොකිරීමට අපි Math.abs () භාවිතා කරමු.


2
අහඹු බිටු ලබා ගැනීමට ඔබ ලෝකයේ UUID භාවිතා කරන්නේ ඇයි? හුදෙක් භාවිතා නොකරන්නේ ඇයි random.nextLong()? නැත්නම් පවා Double.doubleToLongBits(Math.random())?
එරික්සන්

4

ඔබගේ මුරපදය අනිවාර්යයෙන්ම අකාරාදී විශේෂ අක්ෂර අඩංගු නම් ඔබට පහත කේතය භාවිතා කළ හැකිය:

private static final String NUMBERS = "0123456789";
private static final String UPPER_ALPHABETS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String LOWER_ALPHABETS = "abcdefghijklmnopqrstuvwxyz";
private static final String SPECIALCHARACTERS = "@#$%&*";
private static final int MINLENGTHOFPASSWORD = 8;

public static String getRandomPassword() {
    StringBuilder password = new StringBuilder();
    int j = 0;
    for (int i = 0; i < MINLENGTHOFPASSWORD; i++) {
        password.append(getRandomPasswordCharacters(j));
        j++;
        if (j == 3) {
            j = 0;
        }
    }
    return password.toString();
}

private static String getRandomPasswordCharacters(int pos) {
    Random randomNum = new Random();
    StringBuilder randomChar = new StringBuilder();
    switch (pos) {
        case 0:
            randomChar.append(NUMBERS.charAt(randomNum.nextInt(NUMBERS.length() - 1)));
            break;
        case 1:
            randomChar.append(UPPER_ALPHABETS.charAt(randomNum.nextInt(UPPER_ALPHABETS.length() - 1)));
            break;
        case 2:
            randomChar.append(SPECIALCHARACTERS.charAt(randomNum.nextInt(SPECIALCHARACTERS.length() - 1)));
            break;
        case 3:
            randomChar.append(LOWER_ALPHABETS.charAt(randomNum.nextInt(LOWER_ALPHABETS.length() - 1)));
            break;
    }
    return randomChar.toString();

}

4

අබාකස්උටිල් විසින් එක් පේළියේ කේතය මෙන්න

String.valueOf(CharStream.random('0', 'z').filter(c -> N.isLetterOrDigit(c)).limit(12).toArray())

අහඹු ලෙස අදහස් කරන්නේ එය අද්විතීය විය යුතු බවයි. අද්විතීය නූල් ලබා ගැනීමට, භාවිතා කරමින්:

N.uuid() // e.g.: "e812e749-cf4c-4959-8ee1-57829a69a80f". length is 36.
N.guid() // e.g.: "0678ce04e18945559ba82ddeccaabfcd". length is 32 without '-'

3

මෙන්න එය Scala විසඳුමකි:

(for (i <- 0 until rnd.nextInt(64)) yield { 
  ('0' + rnd.nextInt(64)).asInstanceOf[Char] 
}) mkString("")


3
public static String randomSeriesForThreeCharacter() {
    Random r = new Random();
    String value="";
    char random_Char ;
    for(int i=0; i<10;i++)
    { 
        random_Char = (char) (48 + r.nextInt(74));
        value=value+random_char;
    }
    return value;
}

2
එම නූල් සම්මුතිය අනවශ්‍ය ලෙස අකාර්යක්ෂම වේ. පිස්සු ඉන්ඩෙන්ටේෂන් මඟින් ඔබේ කේතය කියවීමට නොහැකි තරම්ය. මෙය ජේමිගේ අදහසට සමානය, නමුත් දුර්වල ලෙස ක්‍රියාත්මක වේ.
එරික්සන්

3

මම හිතන්නේ මෙය මෙහි ඇති කුඩාම විසඳුම හෝ කුඩාම එකක් පමණයි:

 public String generateRandomString(int length) {
    String randomString = "";

    final char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890".toCharArray();
    final SecureRandom random = new SecureRandom();
    for (int i = 0; i < length; i++) {
        randomString = randomString + chars[random.nextInt(chars.length)];
    }

    return randomString;
}

කේතය හොඳින් ක්‍රියාත්මක වේ. ඔබ මෙම ක්‍රමය භාවිතා කරන්නේ නම්, අක්ෂර 10 කට වඩා භාවිතා කිරීමට මම ඔබට නිර්දේශ කරමි. Ision ට්ටනය සිදුවන්නේ අක්ෂර 5 කින් / 30362 පුනරාවර්තනයෙනි. මේ සඳහා තත්පර 9 ක් ගතවිය.


3
public static String getRandomString(int length) {
        char[] chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST".toCharArray();

        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            char c = chars[random.nextInt(chars.length)];
            sb.append(c);
        }
        String randomStr = sb.toString();

        return randomStr;
    }

1
ඇත්තෙන්ම හොඳයි! නමුත් එය for for loop lengthවෙනුවට විය යුතුය chars.length: for (int i = 0; i < length; i++)
දහනය කරන්න

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.