यूयूआईडी पुस्तकालय 32-चरित्र यूयूआईडी उत्पन्न करते हैं।
मैं केवल 8 UUIDs उत्पन्न करना चाहता हूं, क्या यह संभव है?
यूयूआईडी पुस्तकालय 32-चरित्र यूयूआईडी उत्पन्न करते हैं।
मैं केवल 8 UUIDs उत्पन्न करना चाहता हूं, क्या यह संभव है?
जवाबों:
यह संभव नहीं है क्योंकि यूयूआईडी प्रति परिभाषा 16-बाइट संख्या है। लेकिन निश्चित रूप से, आप 8-वर्ण लंबी अनूठी स्ट्रिंग्स उत्पन्न कर सकते हैं (अन्य उत्तर देखें)।
इसके अलावा अधिक समय तक यूयूआईडी उत्पन्न करने और उन्हें प्रतिस्थापित करने के साथ सावधान रहें, क्योंकि आईडी के कुछ हिस्सों में निश्चित बाइट्स हो सकते हैं (जैसे कि मैक, डीसीई और एमडी 5 यूयूआईडी के साथ यही स्थिति है)।
आप RandomStringUtils
apache.commons से क्लास ट्राई कर सकते हैं :
import org.apache.commons.lang3.RandomStringUtils;
final int SHORT_ID_LENGTH = 8;
// all possible unicode characters
String shortId = RandomStringUtils.random(SHORT_ID_LENGTH);
कृपया ध्यान रखें, इसमें सभी संभव अक्षर होंगे जो न तो URL है और न ही मानव के अनुकूल।
इसलिए अन्य तरीकों की भी जाँच करें:
// HEX: 0-9, a-f. For example: 6587fddb, c0f182c1
shortId = RandomStringUtils.random(8, "0123456789abcdef");
// a-z, A-Z. For example: eRkgbzeF, MFcWSksx
shortId = RandomStringUtils.randomAlphabetic(8);
// 0-9. For example: 76091014, 03771122
shortId = RandomStringUtils.randomNumeric(8);
// a-z, A-Z, 0-9. For example: WRMcpIk7, s57JwCVA
shortId = RandomStringUtils.randomAlphanumeric(8);
जैसा कि अन्य लोगों ने कहा कि छोटी आईडी के साथ आईडी के टकराने की संभावना महत्वपूर्ण हो सकती है। देखें कि आपके मामले में जन्मदिन की समस्या कैसे लागू होती है। इस उत्तर में सन्निकटन की गणना कैसे करें, आप अच्छी व्याख्या पा सकते हैं ।
org.apache.commons.lang3.RandomStringUtils
हटा दिया गया है, तो आप बेहतर उपयोग करते हुए हो जाएगा org.apache.commons.text.RandomStringGenerator
में commons.apache.org/proper/commons-text
RandomStringGenerator
, क्योंकि यह काफी अलग कोड है।
RandomStringUtils
पदावनत नहीं किया जाता है। यह सरल उपयोग के लिए अभिप्रेत है। क्या आप उस जानकारी का स्रोत प्रदान कर सकते हैं जो RandomStringUtils
पदावनत है? मैं RandomStringUtils
एक प्रमाण के रूप में नवीनतम संस्करण का प्रलेखन प्रदान कर सकता हूं कि यह पदावनत नहीं किया गया है: commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/……
पहला: यहां तक कि जावा यूयूआईडी.randomUUID या .net GUID द्वारा उत्पन्न अद्वितीय आईडी 100% अद्वितीय नहीं हैं। विशिष्ट UUID.randomUUID "केवल" एक 128 बिट (सुरक्षित) यादृच्छिक मूल्य है। इसलिए यदि आप इसे 64 बिट, 32 बिट, 16 बिट (या यहां तक कि 1 बिट) तक कम कर देते हैं तो यह बस कम अद्वितीय बन जाता है।
इसलिए यह कम से कम जोखिम आधारित निर्णय है, आपका यूआईडी कब तक होना चाहिए।
दूसरा: मेरा मानना है कि जब आप "केवल 8 वर्णों" के बारे में बात करते हैं तो आपका मतलब है 8 सामान्य मुद्रण योग्य वर्णों का एक स्ट्रिंग।
यदि आप लंबाई 8 मुद्रण योग्य वर्णों के साथ एक अद्वितीय स्ट्रिंग चाहते हैं तो आप एक बेस 64 एन्कोडिंग का उपयोग कर सकते हैं। इसका मतलब है 6 बिट प्रति चार्ट, इसलिए आपको कुल 48bit मिलता है (संभव है कि बहुत अनूठा न हो - लेकिन शायद यह आपके लिए ठीक है)
तो रास्ता आसान है: एक 6 बाइट यादृच्छिक सरणी बनाएँ
SecureRandom rand;
// ...
byte[] randomBytes = new byte[16];
rand.nextBytes(randomBytes);
और फिर इसे एक बेस 64 स्ट्रिंग में बदल दें, उदाहरण के लिए org.apache.commons.codec.binary.Base64
BTW: यह आपके आवेदन पर निर्भर करता है अगर "uuid" बनाने का एक बेहतर तरीका है तो यादृच्छिक। (यदि आप प्रति सेकंड केवल एक बार UUIDs बनाते हैं, तो टाइम स्टैंप को जोड़ना एक अच्छा विचार है) (वैसे: यदि आप दो यादृच्छिक मूल्यों को जोड़ते हैं (xor), तो परिणाम हमेशा कम से कम यादृच्छिक रूप से सबसे अधिक होता है दोनों का यादृच्छिक)।
जैसा कि @Cephalopod ने कहा कि यह संभव नहीं है, लेकिन आप यूयूआईडी को 22 अक्षरों में छोटा कर सकते हैं
public static String encodeUUIDBase64(UUID uuid) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return StringUtils.trimTrailingCharacter(BaseEncoding.base64Url().encode(bb.array()), '=');
}
यह एक ऐसा ही तरीका है जिसका उपयोग मैं यहां एक अनोखा त्रुटि कोड जनरेट करने के लिए कर रहा हूं, जो कि एंटोन पुरीन के उत्तर पर आधारित है, लेकिन org.apache.commons.text.RandomStringGenerator
(एक बार, अब और नहीं) के बजाय अधिक उपयुक्त पर निर्भर करता है org.apache.commons.lang3.RandomStringUtils
:
@Singleton
@Component
public class ErrorCodeGenerator implements Supplier<String> {
private RandomStringGenerator errorCodeGenerator;
public ErrorCodeGenerator() {
errorCodeGenerator = new RandomStringGenerator.Builder()
.withinRange('0', 'z')
.filteredBy(t -> t >= '0' && t <= '9', t -> t >= 'A' && t <= 'Z', t -> t >= 'a' && t <= 'z')
.build();
}
@Override
public String get() {
return errorCodeGenerator.generate(8);
}
}
टक्कर के बारे में सभी सलाह अभी भी लागू होती हैं, कृपया उनके बारे में पता करें।
RandomStringUtils
पदावनत नहीं किया जाता है। यह सरल उपयोग के लिए अभिप्रेत है। क्या आप उस जानकारी का एक स्रोत प्रदान कर सकते हैं जो RandomStringUtils
पदावनत है? मैं RandomStringUtils
एक प्रमाण के रूप में नवीनतम संस्करण के प्रलेखन प्रदान कर सकता हूं कि यह पदावनत नहीं किया गया है: commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/……
commons.lang
कि वैसे भी भाषा से कड़ाई से संबंधित नहीं है, commons.text
एक उद्देश्य के साथ बनाया गया था।
RandomStringUtils
में पदावनत नहीं किया जाता है और आपके द्वारा उपलब्ध कराए गए संदर्भों के अनुसार इसे हटाए नहीं रखने का एक अच्छा कारण है, क्योंकि यह RandomStringGenerator
सरल उपयोग के मामलों की तुलना में उपयोग करने के लिए बहुत सरल है । शायद आप अपना जवाब अपडेट कर सकते हैं? यदि / जब RandomStringUtils
या साधारण उपयोग के मामलों के लिए इसकी कार्यक्षमता को स्थानांतरित कर दिया जाएगा commons.text
, तो आप अपने उत्तर को फिर से अपडेट कर सकते हैं, लेकिन वर्तमान में यह भ्रामक है।
commons.lang
है commons.text
, किसी के लिए पूर्ववर्ती का उपयोग करने के बजाय किसी अन्य के लिए इसका उपयोग करने का कोई कारण नहीं है क्योंकि यह पहले से कहीं और उपयोग कर रहा है। यहाँ सादगी बल्कि व्यक्तिपरक है, मुझे अपना उत्तर अभी भी बहुत सरल लगता है, और मैं इसे कभी भी किसी ऐसी चीज के लिए नहीं बदलूंगा जिसके लिए कॉमन्स लैंग को आयात करना होगा।
इसके बारे में क्या खयाल है? दरअसल, यह कोड अधिकतम 13 वर्ण देता है, लेकिन यह UUID से कम है।
import java.nio.ByteBuffer;
import java.util.UUID;
/**
* Generate short UUID (13 characters)
*
* @return short UUID
*/
public static String shortUUID() {
UUID uuid = UUID.randomUUID();
long l = ByteBuffer.wrap(uuid.toString().getBytes()).getLong();
return Long.toString(l, Character.MAX_RADIX);
}
getLong()
केवल बफर के पहले 8 बाइट्स को पढ़ना है। यूयूआईडी में कम से कम 36 बाइट होंगी। क्या मुझे कुछ याद आ रहा है क्योंकि मेरे लिए यह कभी काम नहीं करेगा।
वास्तव में मैं टाइमस्टैम्प आधारित छोटी विशिष्ट पहचानकर्ता चाहता हूं, इसलिए नीचे दिए गए कार्यक्रम की कोशिश की।
यह nanosecond + ( endians.length * endians.length )
संयोजनों के साथ अनुमान लगाने योग्य है ।
public class TimStampShorterUUID {
private static final Character [] endians =
{'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',
'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'
};
private static ThreadLocal<Character> threadLocal = new ThreadLocal<Character>();
private static AtomicLong iterator = new AtomicLong(-1);
public static String generateShorterTxnId() {
// Keep this as secure random when we want more secure, in distributed systems
int firstLetter = ThreadLocalRandom.current().nextInt(0, (endians.length));
//Sometimes your randomness and timestamp will be same value,
//when multiple threads are trying at the same nano second
//time hence to differentiate it, utilize the threads requesting
//for this value, the possible unique thread numbers == endians.length
Character secondLetter = threadLocal.get();
if (secondLetter == null) {
synchronized (threadLocal) {
if (secondLetter == null) {
threadLocal.set(endians[(int) (iterator.incrementAndGet() % endians.length)]);
}
}
secondLetter = threadLocal.get();
}
return "" + endians[firstLetter] + secondLetter + System.nanoTime();
}
public static void main(String[] args) {
Map<String, String> uniqueKeysTestMap = new ConcurrentHashMap<>();
Thread t1 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t3 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t4 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t5 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t6 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t7 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
}
}
अपडेट करें : यह कोड एकल JVM पर काम करेगा, लेकिन हमें वितरित JVM पर सोचना चाहिए, इसलिए मैं DB के साथ दो समाधान सोच रहा हूं और DB के बिना एक और।
डीबी के साथ
कंपनी का नाम (शोर्टनाम 3 चार्ट्स) ---- रैंडम_Number ---- प्रमुख विशिष्ट रेडीस कॉर्नर
(3 चार) -------------------------- ---------------------- (2 char) ---------------- (11 char)
बिना डी.बी.
IPADDRESS ---- THREAD_NUMBER ---- INCR_NUMBER ---- युगीन मिलीसेकंड
(5 वर्ण) ----------------- (2char) --------- -------------- (2 char) ----------------- (6 char)
कोडिंग हो जाने के बाद आपको अपडेट करेगा।
UUID नहीं, लेकिन यह मेरे लिए काम करता है:
UUID.randomUUID().toString().replace("-","").substring(0,8)
मुझे नहीं लगता कि यह संभव है लेकिन आपके पास एक अच्छा समाधान है।
new Random(System.currentTimeMillis()).nextInt(99999999);
यह 8 अक्षर तक की यादृच्छिक आईडी उत्पन्न करेगा।अल्फ़ान्यूमेरिक आईडी बनाएँ:
char[] chars = "abcdefghijklmnopqrstuvwxyzABSDEFGHIJKLMNOPQRSTUVWXYZ1234567890".toCharArray();
Random r = new Random(System.currentTimeMillis());
char[] id = new char[8];
for (int i = 0; i < 8; i++) {
id[i] = chars[r.nextInt(chars.length)];
}
return new String(id);