Create only 8 character UUIDs

UUID libraries generate 32-character UUIDs.

I want to generate only 8 character UUIDs, is this possible?

+62
java uuid
Nov 24 '10 at 13:50
source share
8 answers

This is not possible because the UUID is a 16-byte number for each definition. But of course, you can generate 8-character long unique strings (see other answers).

Also be careful about generating longer UUIDs and their substring, as some parts of the identifier may contain fixed bytes (for example, this happens with MAC, DCE and MD5 UUIDs).

+55
Nov 24 '10 at 14:26
source share

You can try the RandomStringUtils class from 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); 

Please keep in mind that it will contain all possible characters that are neither URL nor human friendly.

So try other methods too:

 // HEX: 0-9, af. For example: 6587fddb, c0f182c1 shortId = RandomStringUtils.random(8, "0123456789abcdef"); // az, AZ. For example: eRkgbzeF, MFcWSksx shortId = RandomStringUtils.randomAlphabetic(8); // 0-9. For example: 76091014, 03771122 shortId = RandomStringUtils.randomNumeric(8); // az, AZ, 0-9. For example: WRMcpIk7, s57JwCVA shortId = RandomStringUtils.randomAlphanumeric(8); 

As others have said, the likelihood of an identifier colliding with a smaller identifier can be significant. Check how the birthday issue relates to your case. You can find a good explanation on how to calculate the approximation in this answer .

+31
Jul 12 '17 at 10:55 on
source share

Firstly: even the unique identifiers generated by the java UUID.randomUUID or .net GUID are not 100% unique. Especialy UUID.randomUUID is a β€œonly” 128-bit (secure) random value. Therefore, if you reduce it to 64 bits, 32 bits, 16 bits (or even 1 bit), then it will simply become less unique.

So, these are at least risk-based decisions for how long your uuid should be.

Secondly: I assume that when you talk about β€œonly 8 characters,” you mean a string of 8 ordinary printable characters.

If you need a unique string of 8 printable characters, you can use base64 encoding. That means 6 bits per char, so you only get 48 bits (maybe not very unique - but maybe this is fine for your application)

So the way is simple: create a 6-byte random array

  SecureRandom rand; // ... byte[] randomBytes = new byte[16]; rand.nextBytes(randomBytes); 

And then convert it to a Base64 string, e.g. org.apache.commons.codec.binary.Base64

By the way: it depends on your application if there is a better way to create "uuid" and then randomly. (If you create a UUID only once per second, then it's a good idea to add a timestamp) (By the way: if you combine (xor) two random values, the result will always be at least as random as the most random of both).

+15
Nov 24 '10 at 15:31
source share

As @Cephalopod noted, this is not possible, but you can reduce the UUID to 22 characters

 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()), '='); } 
+5
Sep 15 '16 at 16:04
source share

This is a similar way that I use here to generate a unique error code based on Anton Purin's answer, but relying on more suitable org.apache.commons.text.RandomStringGenerator instead of (once no longer obsolete) 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); } } 

All collision tips still apply, please keep in mind.

+3
Dec 10 '17 at 16:16
source share

In fact, I want a shorter unique identifier based on a timestamp, so I tried the program below.

This is possible with 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(); } } 

UPDATE This code will work on one JVM, but we should think about a distributed JVM, so I am thinking of two solutions with DB and another without DB.

with DB

Company name (short name 3 characters) ---- Random_Number ---- Key specific to redis COUNTER
(3 char) -------------------------------------------- - - (2 char) ---------------- (11 char)

without DB

IPADDRESS ---- THREAD_NUMBER ---- INCR_NUMBER ---- epoch milliseconds
(5 characters) ----------------- (2char) ----------------------- (2 char ) ----------------- (6 char)

will update you after coding is complete.

+1
Sep 06 '17 at 9:12 on
source share

How about this? In fact, this code returns a maximum of 13 characters, but it is less than the 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); } 
-one
Jun 19 '13 at 5:06 on
source share

I don't think this is possible, but you have a good workaround.

  • cut the end of your UUID with substring ()
  • use the code new Random(System.currentTimeMillis()).nextInt(99999999); this generates a random identifier up to 8 characters long.
  • generate alphanumeric identifier:

     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); 
-12
Nov 24 2018-10-14
source share



All Articles