JAVA में UUID स्ट्रिंग उत्पन्न करने के लिए कुशल विधि (UUID.randomUUID (), स्ट्रासिंग () डैश के बिना)


154

मैं बाइट्स के अनूठे दृश्यों को उत्पन्न करने के लिए एक कुशल उपयोगिता चाहूंगा। UUID एक अच्छा उम्मीदवार है लेकिन UUID.randomUUID().toString()सामान की तरह उत्पन्न करता है44e128a5-ac7a-4c9a-be4c-224b6bf81b20 है, लेकिन वह जो अच्छा है, लेकिन मैं डैश-कम स्ट्रिंग पसंद करूंगा।

मैं केवल अल्फ़ान्यूमेरिक वर्ण (कोई डैश या कोई अन्य विशेष चिह्न) से एक यादृच्छिक स्ट्रिंग्स उत्पन्न करने के लिए एक कुशल तरीके की तलाश कर रहा हूं।


38
ऐसे UUID को HTTP पर प्रसारित करने के लिए डैश को हटाने की आवश्यकता क्यों है?
ब्रूनो

6
मुझे नहीं लगा कि सामान्य रूप से HTTP में हटाए जाने की आवश्यकता है ... जो आपको परेशान कर रहा है?
जॉन स्कीट

2
शायद एक मोबाइल वातावरण में, यदि आप अभी भी प्रत्येक बाइट प्रेषित के लिए भुगतान करते हैं, और कम-बैंडविड्थ और उच्च-विलंबता नेटवर्क का उपयोग करते हुए, 4 बाइट्स सहेजना कुछ परिदृश्यों में अभी भी महत्वपूर्ण है ...
Guido

2
मैं चाहता हूं कि डैश को हटा दिया जाए क्योंकि हम बाद में यूयूआईडी स्ट्रिंग को अद्वितीय अनुरोध पहचानकर्ता के रूप में उपयोग करते हैं, यह केवल हेक्स दशमलव वर्णों के साथ काम करना बहुत आसान है [ए-एफ0-9-]।
मैक्सिम वीक्स्लेर

मैंने HTTP भाग को हटा दिया है क्योंकि यह प्रासंगिक नहीं है (जैसा कि मैक्सिम ने समझाया है), केवल पाठकों को भ्रमित करता है (जैसा कि टिप्पणियों और उत्तर दोनों में देखा जा सकता है)।
ओंद्रा kaižka

जवाबों:


274

यह यह करता है:

public static void main(String[] args) {
    final String uuid = UUID.randomUUID().toString().replace("-", "");
    System.out.println("uuid = " + uuid);
}

उदाहरण के लिए, Mongodb ObjectID में डैश का उपयोग नहीं करता है। तो डैश हटाना एपी के लिए उपयोगी हो सकता है।
एलेक्सी रियाज़शिख

1
मैं आपको एक कारण दूंगा। वहाँ एक एपीआई मैं (उच्च प्रोफ़ाइल, अच्छी तरह से ज्ञात) के साथ काम कर रहा हूँ जो अपने यूआईडी में डैश की अनुमति नहीं देता है। आपको उन्हें स्ट्रिप करना होगा।
माइकल गेन्स

19
कोई भी ऐसा करने की आवश्यकता नहीं है, जो नियमित अभिव्यक्ति का उपयोग करे। बस करो .replace ("-", "")
क्रेगो

1
स्ट्रिंग क्लास की जगह विधि थोड़ी धीमी है, मुझे लगता है
bmscomp

@bmscomp पहले आह्वान के लिए, यह धीमा है, लेकिन अगले आह्वान के लिए, कोई समस्या नहीं है।
गौरव

30

डैश को HTTP अनुरोध से निकालने की आवश्यकता नहीं है जैसा कि आप इस थ्रेड के URL में देख सकते हैं। लेकिन अगर आप डेटा पर निर्भरता के बिना अच्छी तरह से गठित URL तैयार करना चाहते हैं, तो आपको अपने डेटा के मानक रूप को बदलने के बजाय URLEncoder.encode (स्ट्रिंग डेटा, स्ट्रिंग एन्कोडिंग) का उपयोग करना चाहिए। UUID स्ट्रिंग प्रतिनिधित्व के लिए डैश सामान्य है।


"डैश को HTTP अनुरोध से निकालने की आवश्यकता नहीं है क्योंकि आप इस धागे के URL में देख सकते हैं।" तब तक नहीं समझें, जब तक कि स्टैक ओवरफ्लो ने पहले अपने यूआरआईडी में यूयूआईडी का इस्तेमाल नहीं किया हो?
RenniePet

1
ऐसा नहीं है कि यूआरएल एक यूयूआईडी है, लेकिन इसमें डैश हैं:http://stackoverflow.com/questions/3804591/efficient-method-to-generate-uuid-string-in-java-uuid-randomuuid-tostring-w?rq=1
ओक्टाविया तोगामी

12

UUID.java कार्यान्वयन के आधार पर अपनी खुद की कुछ लिखने की समाप्ति। ध्यान दें कि मैं एक UUID उत्पन्न नहीं कर रहा हूं , इसके बजाय मैं सबसे कुशल तरीके से एक यादृच्छिक 32 बाइट्स हेक्स स्ट्रिंग के बारे में सोच सकता हूं।

कार्यान्वयन

import java.security.SecureRandom;
import java.util.UUID;

public class RandomUtil {
    // Maxim: Copied from UUID implementation :)
    private static volatile SecureRandom numberGenerator = null;
    private static final long MSB = 0x8000000000000000L;

    public static String unique() {
        SecureRandom ng = numberGenerator;
        if (ng == null) {
            numberGenerator = ng = new SecureRandom();
        }

        return Long.toHexString(MSB | ng.nextLong()) + Long.toHexString(MSB | ng.nextLong());
    }       
}

प्रयोग

RandomUtil.unique()

टेस्ट

कुछ इनपुट्स जो मैंने परीक्षण किए हैं यह सुनिश्चित करने के लिए कि यह काम कर रहा है:

public static void main(String[] args) {
    System.out.println(UUID.randomUUID().toString());
    System.out.println(RandomUtil.unique());

    System.out.println();
    System.out.println(Long.toHexString(0x8000000000000000L |21));
    System.out.println(Long.toBinaryString(0x8000000000000000L |21));
    System.out.println(Long.toHexString(Long.MAX_VALUE + 1));
}

1
यह सुनिश्चित नहीं है कि इसे अधिक क्यों उतारा गया है, इसने यहां लिखे सभी विकल्पों में से सबसे कुशल विधि में "-" के बिना UUID को उत्पन्न किया। स्ट्रिंग रिप्लेसमेंट बेहतर नहीं है तो लंबी से स्ट्रिंग में रूपांतरण। यह सच है कि दोनों ओ (एन) हैं, फिर भी पैमाने पर जहां आप एक मिनट में लाखों यूयूड उत्पन्न करते हैं, यह सार्थक हो जाता है।
बजे मैक्सिम वीक्स्लर

10

यूनिक आईडी जनरेट करने के लिए मैंने JUG (Java UUID जेनरेटर) का इस्तेमाल किया। यह JVMs में अद्वितीय है। उपयोग करने के लिए बहुत अच्छा है। यहाँ आपके संदर्भ के लिए कोड है:

private static final SecureRandom secureRandom = new SecureRandom();
private static final UUIDGenerator generator = UUIDGenerator.getInstance();

public synchronized static String generateUniqueId() {
  UUID uuid = generator.generateRandomBasedUUID(secureRandom);

  return uuid.toString().replaceAll("-", "").toUpperCase();
}

आप लाइब्रेरी को यहां से डाउनलोड कर सकते हैं: https://github.com/cowtowncoder/java-uuid-generator


आपके मामले के लिए UUID.randomUUID () .String () में क्या गलत है? यह भी ध्यान दें कि आप (सैद्धांतिक रूप से) स्थैतिक अंतिम सिक्योर रेंडम को पकड़कर इसे कम कर देते हैं (इसे अस्थिर बनाते हैं)। यह भी कि जनरेटयूनाइक को सिंक्रोनाइज़ क्यों करें? इसका मतलब है कि आपके सभी धागे इस विधि पर अवरुद्ध हैं।
मैक्सिम वीक्स्लेर

सबसे पहले, Safehaus का दावा है कि JUG तेज़ है। और यह उन मशीनों में अद्वितीय आईडी उत्पन्न कर सकता है जिनकी आपको आवश्यकता नहीं है। उनके पास समय-आधारित तरीका है जो सभी तरीकों में सबसे ज्यादा मोटा है। हाँ, यहाँ सिंक्रनाइज़ आवश्यक नहीं है क्योंकि मुझे एहसास हुआ कि सिक्योर रैंडम पहले से ही सुरक्षित है। सिक्योर रैंडम पर स्टेटिक फाइनल की घोषणा करने से एन्ट्रापी में कमी क्यों आएगी? मैं उत्सुक हूँ :) यहाँ और अधिक विवरण हैं: jug.safehaus.org/FAQ
शेंग चिएन

JUG यादृच्छिक-संख्या आधारित UUIDs भी उत्पन्न कर सकता है; लेकिन मुख्य कारण जो डेवलपर्स समय-आधारित संस्करण का उपयोग करना पसंद करते हैं, यह या तो यह है कि यह 10-20x तेज है ( cowtowncoder.com/blog/archives/2010/10/entry_429.html ); या वे अनूठे आईडी (जो थोड़े मजाकिया हैं) का उत्पादन करने के लिए यादृच्छिकता पर भरोसा नहीं करते हैं
स्टैक्समैन

jug.safehaus.org अब मौजूद नहीं है, लेकिन आप में पूछे जाने वाले प्रश्न पा सकते हैं raw.github.com/cowtowncoder/java-uuid-generator/3.0/...
डैनियल Serodio

JUG का उल्लेख करने के लिए +1 - मैंने इसकी उपयोगिता की समीक्षा की है लेकिन यह जानना अच्छा है कि कुछ गंभीर java.util.UUIDविकल्प हैं।
ग्रेग डबकी

8

एक सरल उपाय है

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

(मौजूदा समाधानों की तरह, केवल यह स्ट्रिंग # रिप्लेसमेंट कॉल से बचा जाता है । यहाँ नियमित अभिव्यक्ति प्रतिस्थापन की आवश्यकता नहीं है, इसलिए # रिप्लेसमेंट # अधिक प्राकृतिक लगता है, हालांकि तकनीकी रूप से इसे अभी भी नियमित अभिव्यक्तियों के साथ लागू किया जाता है। प्रतिस्थापन की तुलना में अधिक महंगा, रनटाइम में एक महत्वपूर्ण अंतर नहीं होना चाहिए।)

UUID वर्ग का उपयोग करना संभवत: अधिकांश परिदृश्यों के लिए काफी तेज है, हालांकि मैं उम्मीद करूंगा कि कुछ विशिष्ट हाथ से लिखे गए संस्करण, जिन्हें पोस्टप्रोसेसिंग की आवश्यकता नहीं है, तेज होने के लिए। वैसे भी, समग्र गणना की अड़चन सामान्य रूप से यादृच्छिक संख्या जनरेटर होगी। UUID वर्ग के मामले में, यह SecureRandom का उपयोग करता है

उपयोग करने के लिए कौन सा यादृच्छिक संख्या जनरेटर भी एक व्यापार-बंद है जो आवेदन पर निर्भर करता है। यदि यह सुरक्षा के प्रति संवेदनशील है, तो सिक्योर रैंडम सामान्य रूप से सिफारिश है। अन्यथा, ThreadLocalRandom एक विकल्प (तेज SecureRandom या पुराने की तुलना में है रैंडम , लेकिन क्रिप्टोग्राफी द्वारा सुरक्षित नहीं)।


7

यूयूआईडी के विचारों को प्रतिस्थापित करने वाले इतने सारे तार देखकर मैं चकित हूं। इस बारे में कैसा है:

UUID temp = UUID.randomUUID();
String uuidString = Long.toHexString(temp.getMostSignificantBits())
     + Long.toHexString(temp.getLeastSignificantBits());

यह UUID के पूरे toString () के बाद से ऐसा करने का तेज़ तरीका है, जो पहले से ही नियमित अभिव्यक्ति का उल्लेख नहीं करने के लिए अधिक महंगा है जिसे पार्स और निष्पादित या खाली स्ट्रिंग के साथ प्रतिस्थापित किया जाना है।


6
यह विश्वसनीय नहीं है। आउटपुट छोटा होगा यदि अग्रणी बिट्स 0. हैं
OG Dude

7
String.format("0x%016x%016x", f.getMostSignificantBits(), f.getLeastSignificantBits())
गल्र्स सेप

@galets हालांकि, मैंने 0s के साथ समस्या को हल करने के लिए आपकी टिप्पणी को वोट दिया है, मुझे आश्चर्य है कि क्या डैश का उपयोग करने के विकल्प की तुलना में यह कोई बेहतर होगा replace
igorcadelima


3

मैंने अभी UUID toString () पद्धति की प्रतिलिपि बनाई है और इसे "-" से निकालने के लिए इसे अपडेट किया है। यह किसी भी अन्य समाधान की तुलना में बहुत अधिक तेज और सीधे आगे होगा

public String generateUUIDString(UUID uuid) {
    return (digits(uuid.getMostSignificantBits() >> 32, 8) +
            digits(uuid.getMostSignificantBits() >> 16, 4) +
            digits(uuid.getMostSignificantBits(), 4) +
            digits(uuid.getLeastSignificantBits() >> 48, 4) +
            digits(uuid.getLeastSignificantBits(), 12));
}

/** Returns val represented by the specified number of hex digits. */
private String digits(long val, int digits) {
    long hi = 1L << (digits * 4);
    return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}

उपयोग:

generateUUIDString(UUID.randomUUID())

प्रतिबिंब का उपयोग करते हुए एक और कार्यान्वयन

public String generateString(UUID uuid) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

    if (uuid == null) {
        return "";
    }

    Method digits = UUID.class.getDeclaredMethod("digits", long.class, int.class);
    digits.setAccessible(true);

    return ( (String) digits.invoke(uuid, uuid.getMostSignificantBits() >> 32, 8) +
            digits.invoke(uuid, uuid.getMostSignificantBits() >> 16, 4) +
            digits.invoke(uuid, uuid.getMostSignificantBits(), 4) +
            digits.invoke(uuid, uuid.getLeastSignificantBits() >> 48, 4) +
            digits.invoke(uuid, uuid.getLeastSignificantBits(), 12));

}

2

मैं एक UUID को url-safe यूनिक स्ट्रिंग में परिवर्तित करने के लिए org.apache.commons.codec.binary.Base64 का उपयोग करता हूं जो कि लंबाई में 22 वर्ण है और UUID के समान विशिष्टता है।

मैंने बेस 64 स्टिंग के रूप में स्टोरिंग यूयूआईडी पर अपना कोड पोस्ट किया


0

मैंने इस उपयोगिता वर्ग को लागू किया है जो UUIDs को स्ट्रिंग के साथ या डैश के बिना बनाता है । उपयोग करने और साझा करने के लिए स्वतंत्र। मुझे आशा है कि यह मदद करता है!

package your.package.name;

import java.security.SecureRandom;
import java.util.Random;

/**
 * Utility class that creates random-based UUIDs.
 * 
 */
public abstract class RandomUuidStringCreator {

    private static final int RANDOM_VERSION = 4;

    /**
     * Returns a random-based UUID as String.
     * 
     * It uses a thread local {@link SecureRandom}.
     * 
     * @return a random-based UUID string
     */
    public static String getRandomUuid() {
        return getRandomUuid(SecureRandomLazyHolder.SECURE_RANDOM);
    }

    /**
     * Returns a random-based UUID as String WITH dashes.
     * 
     * It uses a thread local {@link SecureRandom}.
     * 
     * @return a random-based UUID string
     */
    public static String getRandomUuidWithDashes() {
        return format(getRandomUuid());
    }

    /**
     * Returns a random-based UUID String.
     * 
     * It uses any instance of {@link Random}.
     * 
     * @return a random-based UUID string
     */
    public static String getRandomUuid(Random random) {

        long msb = 0;
        long lsb = 0;

        // (3) set all bit randomly
        if (random instanceof SecureRandom) {
            // Faster for instances of SecureRandom
            final byte[] bytes = new byte[16];
            random.nextBytes(bytes);
            msb = toNumber(bytes, 0, 8); // first 8 bytes for MSB
            lsb = toNumber(bytes, 8, 16); // last 8 bytes for LSB
        } else {
            msb = random.nextLong(); // first 8 bytes for MSB
            lsb = random.nextLong(); // last 8 bytes for LSB
        }

        // Apply version and variant bits (required for RFC-4122 compliance)
        msb = (msb & 0xffffffffffff0fffL) | (RANDOM_VERSION & 0x0f) << 12; // apply version bits
        lsb = (lsb & 0x3fffffffffffffffL) | 0x8000000000000000L; // apply variant bits

        // Convert MSB and LSB to hexadecimal
        String msbHex = zerofill(Long.toHexString(msb), 16);
        String lsbHex = zerofill(Long.toHexString(lsb), 16);

        // Return the UUID
        return msbHex + lsbHex;
    }

    /**
     * Returns a random-based UUID as String WITH dashes.
     * 
     * It uses a thread local {@link SecureRandom}.
     * 
     * @return a random-based UUID string
     */
    public static String getRandomUuidWithDashes(Random random) {
        return format(getRandomUuid(random));
    }

    private static long toNumber(final byte[] bytes, final int start, final int length) {
        long result = 0;
        for (int i = start; i < length; i++) {
            result = (result << 8) | (bytes[i] & 0xff);
        }
        return result;
    }

    private static String zerofill(String string, int length) {
        return new String(lpad(string.toCharArray(), length, '0'));
    }

    private static char[] lpad(char[] chars, int length, char fill) {

        int delta = 0;
        int limit = 0;

        if (length > chars.length) {
            delta = length - chars.length;
            limit = length;
        } else {
            delta = 0;
            limit = chars.length;
        }

        char[] output = new char[chars.length + delta];
        for (int i = 0; i < limit; i++) {
            if (i < delta) {
                output[i] = fill;
            } else {
                output[i] = chars[i - delta];
            }
        }
        return output;
    }

    private static String format(String string) {
        char[] input = string.toCharArray();
        char[] output = new char[36];

        System.arraycopy(input, 0, output, 0, 8);
        System.arraycopy(input, 8, output, 9, 4);
        System.arraycopy(input, 12, output, 14, 4);
        System.arraycopy(input, 16, output, 19, 4);
        System.arraycopy(input, 20, output, 24, 12);

        output[8] = '-';
        output[13] = '-';
        output[18] = '-';
        output[23] = '-';

        return new String(output);
    }

    // Holds lazy secure random
    private static class SecureRandomLazyHolder {
        static final Random SECURE_RANDOM = new SecureRandom();
    }

    /**
     * For tests!
     */
    public static void main(String[] args) {

        System.out.println("// Using `java.security.SecureRandom` (DEFAULT)");
        System.out.println("RandomUuidCreator.getRandomUuid()");
        System.out.println();
        for (int i = 0; i < 5; i++) {
            System.out.println(RandomUuidStringCreator.getRandomUuid());
        }

        System.out.println();
        System.out.println("// Using `java.util.Random` (FASTER)");
        System.out.println("RandomUuidCreator.getRandomUuid(new Random())");
        System.out.println();
        Random random = new Random();
        for (int i = 0; i < 5; i++) {
            System.out.println(RandomUuidStringCreator.getRandomUuid(random));
        }
    }
}

यह आउटपुट है:

// Using `java.security.SecureRandom` (DEFAULT)
RandomUuidStringCreator.getRandomUuid()

'f553ca75657b4b5d85bedf1082785a0b'
'525ecc389e934f209b97d0f0db09d9c6'
'93ec6425bb04499ab47b790fd013ab0d'
'c2d438c620ea4cd5baafd448f9fe945b'
'fb4bc5734931415e94e78da62cb5fe0d'

// Using `java.util.Random` (FASTER)
RandomUuidStringCreator.getRandomUuid(new Random())

'051360b5c92d40fbbb89b40842adbacc'
'a993896538aa43faacbcfd83f913f38b'
'720684d22c584d5299cb03cdbc1912d2'
'82cf94ea296a4a138a92825a0068d4a1'
'a7eda46a215c4e55be3aa957ba74ca9c'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.