Unique Id creation of a fixed length

Rishi P picture Rishi P · Nov 11, 2011 · Viewed 8k times · Source

Well, I have been looking at ways to generate UIDs in java code (most of them coming to stackoverflow too). The best is to use java's UUID to create unique ids since it uses the timestamp. But my problem is that it is 128-bit long and I need a shorter string, like say 14 or 15 characters. So, I devised the following code to do so.

Date date = new Date();
Long luid = (Long) date.getTime();
String suid = luid.toString();
System.out.println(suid+": "+suid.length() + " characters");

Random rn = new Random();
Integer long1 = rn.nextInt(9);
Integer long2 = rn.nextInt(13);

String newstr = suid.substring(0, long2) + " " + long1 + " " + suid.subtring(long2);
System.out.println("New string in spaced format: "+newstr);
System.out.println("New string in proper format: "+newstr.replaceAll(" ", ""));

Please note that I am just displaying the spaced-formatted and properly-formatted string for comparison with the original string only.

Would this guarantee a 100% unique id each time? Or do you see any possibility the numbers could be repeated? Also, instead of inserting a random number into a random position which "might" create duplicate numbers, I could do it either in the beginning or end. This is to complete the required length of my UID. Although this might probably not work if you need a UID less than 13 characters.

Any thoughts?

Answer

Gray picture Gray · Nov 16, 2011

This won't work if this is a distributed system of course but how about something like the following.

private AtomicLong uniqueId = new AtomicLong(0);
...
// get a unique current-time-millis value 
long now;
long prev;
do {
    prev = uniqueId.get();
    now = System.currentTimeMillis();
    // make sure now is moving ahead and unique
    if (now <= prev) {
        now = prev + 1;
    }
    // loop if someone else has updated the id
} while (!uniqueId.compareAndSet(prev, now));

// shuffle it
long result = shuffleBits(now);
System.out.println("Result is " + Long.toHexString(result));

public static long shuffleBits(long val) {
    long result = 0;
    result |= (val & 0xFF00000000000000L) >> 56;
    result |= (val & 0x00FF000000000000L) >> 40;
    result |= (val & 0x0000FF0000000000L) >> 24;
    result |= (val & 0x000000FF00000000L) >> 8;
    result |= (val & 0x00000000FF000000L) << 8;
    result |= (val & 0x0000000000FF0000L) << 24;
    result |= (val & 0x000000000000FF00L) << 40;
    result |= (val & 0x00000000000000FFL) << 56;
    return result;
}

The bit shuffling could be improved on to generate more change in the values each iteration. You mentioned that you don't want the numbers to be sequential but you didn't specify a requirement for full random-ness.

Certainly not as good as the UUID but faster then the database operation.