Create a GUID in Java

JavaGuid

Java Problem Overview


What are some of the best ways to create a GUID in Java?

Java Solutions


Solution 1 - Java

java.util.UUID.randomUUID();

Solution 2 - Java

Have a look at the UUID class bundled with Java 5 and later.

For example:

Solution 3 - Java

Just to extend Mark Byers's answer with an example:

import java.util.UUID;

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

Solution 4 - Java

It depends what kind of UUID you want.

  • The standard Java UUID class generates Version 4 (random) UUIDs. (UPDATE - Version 3 (name) UUIDs can also be generated.) It can also handle other variants, though it cannot generate them. (In this case, "handle" means construct UUID instances from long, byte[] or String representations, and provide some appropriate accessors.)

  • The Java UUID Generator (JUG) implementation purports to support "all 3 'official' types of UUID as defined by RFC-4122" ... though the RFC actually defines 4 types and mentions a 5th type.

For more information on UUID types and variants, there is a good summary in Wikipedia, and the gory details are in RFC 4122 and the other specifications.

Solution 5 - Java

The other Answers are correct, especially this one by Stephen C.

Reaching Outside Java

Generating a UUID value within Java is limited to Version 4 (random) because of security concerns.

If you want other versions of UUIDs, one avenue is to have your Java app reach outside the JVM to generate UUIDs by calling on:

  • Command-line utility
    Bundled with nearly every operating system.
    For example, uuidgen found in Mac OS X, BSD, and Linux.
  • Database server
    Use JDBC to retrieve a UUID generated on the database server.
    For example, the uuid-ossp extension often bundled with Postgres. That extension can generates Versions 1, 3, and 4 values and additionally a couple variations:
  • uuid_generate_v1mc() – generates a version 1 UUID but uses a random multicast MAC address instead of the real MAC address of the computer.
  • uuid_generate_v5(namespace uuid, name text) – generates a version 5 UUID, which works like a version 3 UUID except that SHA-1 is used as a hashing method.
  • Web Service
    For example, UUID Generator creates Versions 1 & 3 as well as nil values and GUID.

Solution 6 - Java

This answer contains 2 generators for random-based and name-based UUIDs, compliant with RFC-4122. Feel free to use and share.

RANDOM-BASED (v4)

This utility class that generates random-based UUIDs:

package your.package.name;

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

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

	private static final int RANDOM_VERSION = 4;

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

	/**
	 * Returns a random-based UUID.
	 * 
	 * It uses any instance of {@link Random}.
	 * 
	 * @return a random-based UUID
	 */
	public static UUID 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

		// Return the UUID
		return new UUID(msb, lsb);
	}

	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;
	}

	// Holds thread local secure random
	private static class SecureRandomLazyHolder {
		static final ThreadLocal<Random> THREAD_LOCAL_RANDOM = ThreadLocal.withInitial(SecureRandom::new);
	}

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

		System.out.println("// Using thread local `java.security.SecureRandom` (DEFAULT)");
		System.out.println("RandomUuidCreator.getRandomUuid()");
		System.out.println();
		for (int i = 0; i < 5; i++) {
			System.out.println(RandomUuidCreator.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(RandomUuidCreator.getRandomUuid(random));
		}
	}
}

This is the output:

// Using thread local `java.security.SecureRandom` (DEFAULT)
RandomUuidCreator.getRandomUuid()

'ef4f5ad2-8147-46cb-8389-c2b8c3ef6b10'
'adc0305a-df29-4f08-9d73-800fde2048f0'
'4b794b59-bff8-4013-b656-5d34c33f4ce3'
'22517093-ee24-4120-96a5-ecee943992d1'
'899fb1fb-3e3d-4026-85a8-8a2d274a10cb'

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

'4dabbbc2-fcb2-4074-a91c-5e2977a5bbf8'
'078ec231-88bc-4d74-9774-96c0b820ceda'
'726638fa-69a6-4a18-b09f-5fd2a708059b'
'15616ebe-1dfd-4f5c-b2ed-cea0ac1ad823'
'affa31ad-5e55-4cde-8232-cddd4931923a'

NAME-BASED (v3 and v5)

This utility class that generates name-based UUIDs (MD5 and SHA1):

package your.package.name;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

/**
 * Utility class that creates UUIDv3 (MD5) and UUIDv5 (SHA1).
 *
 */
public class HashUuidCreator {

	// Domain Name System
	public static final UUID NAMESPACE_DNS = new UUID(0x6ba7b8109dad11d1L, 0x80b400c04fd430c8L);
	// Uniform Resource Locator
	public static final UUID NAMESPACE_URL = new UUID(0x6ba7b8119dad11d1L, 0x80b400c04fd430c8L);
	// ISO Object ID
	public static final UUID NAMESPACE_ISO_OID = new UUID(0x6ba7b8129dad11d1L, 0x80b400c04fd430c8L);
	// X.500 Distinguished Name
	public static final UUID NAMESPACE_X500_DN = new UUID(0x6ba7b8149dad11d1L, 0x80b400c04fd430c8L);

	private static final int VERSION_3 = 3; // UUIDv3 MD5
	private static final int VERSION_5 = 5; // UUIDv5 SHA1

	private static final String MESSAGE_DIGEST_MD5 = "MD5"; // UUIDv3
	private static final String MESSAGE_DIGEST_SHA1 = "SHA-1"; // UUIDv5

	private static UUID getHashUuid(UUID namespace, String name, String algorithm, int version) {

		final byte[] hash;
		final MessageDigest hasher;

		try {
			// Instantiate a message digest for the chosen algorithm
			hasher = MessageDigest.getInstance(algorithm);

			// Insert name space if NOT NULL
			if (namespace != null) {
				hasher.update(toBytes(namespace.getMostSignificantBits()));
				hasher.update(toBytes(namespace.getLeastSignificantBits()));
			}

			// Generate the hash
			hash = hasher.digest(name.getBytes(StandardCharsets.UTF_8));

			// Split the hash into two parts: MSB and LSB
			long msb = toNumber(hash, 0, 8); // first 8 bytes for MSB
			long lsb = toNumber(hash, 8, 16); // last 8 bytes for LSB

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

			// Return the UUID
			return new UUID(msb, lsb);

		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("Message digest algorithm not supported.");
		}
	}

	public static UUID getMd5Uuid(String string) {
		return getHashUuid(null, string, MESSAGE_DIGEST_MD5, VERSION_3);
	}

	public static UUID getSha1Uuid(String string) {
		return getHashUuid(null, string, MESSAGE_DIGEST_SHA1, VERSION_5);
	}

	public static UUID getMd5Uuid(UUID namespace, String string) {
		return getHashUuid(namespace, string, MESSAGE_DIGEST_MD5, VERSION_3);
	}

	public static UUID getSha1Uuid(UUID namespace, String string) {
		return getHashUuid(namespace, string, MESSAGE_DIGEST_SHA1, VERSION_5);
	}

	private static byte[] toBytes(final long number) {
		return new byte[] { (byte) (number >>> 56), (byte) (number >>> 48), (byte) (number >>> 40),
				(byte) (number >>> 32), (byte) (number >>> 24), (byte) (number >>> 16), (byte) (number >>> 8),
				(byte) (number) };
	}

	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;
	}

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

		String string = "JUST_A_TEST_STRING";
		UUID namespace = UUID.randomUUID(); // A custom name space

		System.out.println("Java's generator");
		System.out.println("UUID.nameUUIDFromBytes():      '" + UUID.nameUUIDFromBytes(string.getBytes()) + "'");
		System.out.println();
		System.out.println("This generator");
		System.out.println("HashUuidCreator.getMd5Uuid():  '" + HashUuidCreator.getMd5Uuid(string) + "'");
		System.out.println("HashUuidCreator.getSha1Uuid(): '" + HashUuidCreator.getSha1Uuid(string) + "'");
		System.out.println();
		System.out.println("This generator WITH name space");
		System.out.println("HashUuidCreator.getMd5Uuid():  '" + HashUuidCreator.getMd5Uuid(namespace, string) + "'");
		System.out.println("HashUuidCreator.getSha1Uuid(): '" + HashUuidCreator.getSha1Uuid(namespace, string) + "'");
	}
}

This is the output:

// Java's generator
UUID.nameUUIDFromBytes():      '9e120341-627f-32be-8393-58b5d655b751'

// This generator
HashUuidCreator.getMd5Uuid():  '9e120341-627f-32be-8393-58b5d655b751'
HashUuidCreator.getSha1Uuid(): 'e4586bed-032a-5ae6-9883-331cd94c4ffa'

// This generator WITH name space
HashUuidCreator.getMd5Uuid():  '2b098683-03c9-3ed8-9426-cf5c81ab1f9f'
HashUuidCreator.getSha1Uuid(): '1ef568c7-726b-58cc-a72a-7df173463bbb'

ALTERNATE GENERATOR

You can also use the uuid-creator library. See these examples:

// Create a random-based UUID
UUID uuid = UuidCreator.getRandomBased();
// Create a name based UUID (SHA1)
String name = "JUST_A_TEST_STRING";
UUID uuid = UuidCreator.getNameBasedSha1(name);

Project page: https://github.com/f4b6a3/uuid-creator

Solution 7 - Java

For many cases, we need global UUID for objects and especially in Event-Driven Architecture or Event Sourcing we have to sort events based on the date, but we don't need full information about timestamps.

There we can use one of the implementations of ULID which is lexicographically sortable.

The format is different from standard UUID, but is still simple:

example value: 01AN4Z07BY79KA1307SR9X4MV3

 01AN4Z07BY      79KA1307SR9X4MV3

|----------|    |----------------|
 Timestamp          Randomness
   48bits             80bits

There are implementations in many languages.

For example in Java, there is simple lib for that.

Code example:

import de.huxhorn.sulky.ulid.ULID;

ULID ulid = new ULID();

// with current timestamp
String newId = ulid.nextULID(); 

// with selected timestamp
String newId2 = ulid.nextULID(Instant
    .parse("2021-12-01T00:00:00.00Z")
    .toEpochMilli()
); 

With Spring you can create Bean for ULID generator as well.

@Configuration
public class UUIDGeneratorConfig {

    @Bean
    public ULID ulidGenerator() {
        return new ULID();
    }
}
@Component
public class ULIDGenerator {

    private final ULID ulid;

    public ULIDGenerator(ULID ulid) {
        this.ulid = ulid;
    }

    public String generateUUID() {
        return ulid.nextULID();
    }

    public String generateUUID(Instant timestamp) {
        return ulid.nextULID(timestamp.toEpochMilli());
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChris DutrowView Question on Stackoverflow
Solution 1 - JavaKaleb BraseeView Answer on Stackoverflow
Solution 2 - JavaMark ByersView Answer on Stackoverflow
Solution 3 - JavaAnton BelevView Answer on Stackoverflow
Solution 4 - JavaStephen CView Answer on Stackoverflow
Solution 5 - JavaBasil BourqueView Answer on Stackoverflow
Solution 6 - JavafabiolimaceView Answer on Stackoverflow
Solution 7 - JavaM. DudekView Answer on Stackoverflow