UUID stands for "Universally Unique Identifier." It's a way to give a unique identity to something, like a piece of information or an object, in the world of computing. The key word here is "unique" – it means that no two things should have the same UUID.
For example, Think of it like an Aadhar number for a person. Each person has a unique Aadhar number that helps to identify the person.
Different versions of UUIDs
UUID v1 (Time-based)
UUID type 1 use the current timestamp with a node identifier to generate a unique code.
UUID v2 (DCE Security)
UUID v2 closely resembles UUID v1, with the addition of an enhanced security layer. It strengthens security by substituting the least significant bits of the clock sequence and timestamp with a local domain number and a meaningful identifier. This modification renders UUID v2 particularly well-suited for applications with elevated security requirements.
UUID v3 (MD5-based name UUID)
UUID v3 generates a unique code based on a combination of a namespace and a name. It uses the MD5 hashing algorithm to convert the namespace and name into a 128-bit hash value, which is then used to create the UUID. This type of UUID is useful for identifying objects within a specific namespace, such as files in a file system.
UUID v4 (Random UUID)
UUID v4 is the most commonly used type of UUID. It generates a completely random 128-bit code, ensuring that the UUID is extremely unlikely to collide with any other UUID.
UUID v5 (SHA-1-based name UUID)
Just like UUID v3, UUID v5 creates a special code using a mix of a category and a name. The difference is that it uses SHA-1 to make this code. This type of UUID is good for applications that need both a one-of-a-kind code and extra security.
Deterministic and non-deterministic UUIDs
A deterministic UUID is made from an input that you can expect, so if you use the same input, you'll always get the same result. On the other hand, a non-deterministic UUID comes from a random input, so you always get a different result.
People often use deterministic UUIDs when they need to consistently identify the same thing over time. For instance, they're commonly employed to create UUIDs for database records. On the flip side, non-deterministic UUIDs are preferred in situations where privacy is crucial. For example, they're frequently used to generate UUIDs for user sessions.
UUID type 2, 3 and 5 are deterministic algorithms, whereas type 1 and 4 are non-deterministic algorithms.
Following utility class generate uuid for the types 1, 3, 4 and 5.
UUIDGenerator.java
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
public class UUIDGenerator {
private static long getNodeId() {
try {
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
byte[] macAddress = networkInterface.getHardwareAddress();
if (macAddress != null) {
long nodeID = 0;
for (int i = 0; i < 6; i++) {
nodeID = (nodeID << 8) | (macAddress[i] & 0xFF);
}
return nodeID;
}
} catch (Exception e) {
// Ignore exception
}
return (long) Math.random() * Long.MAX_VALUE;
}
public static UUID generateUUID1() {
long timestamp = System.currentTimeMillis();
long nodeID = getNodeId();
return new UUID(timestamp, nodeID);
}
public static UUID generateUUID3(String namespace, String name) {
return generateNameBasedUUID(namespace, name, "MD5", 3);
}
public static UUID generateUUID4() {
return UUID.randomUUID();
}
public static UUID generateUUID5(String namespace, String name) {
return generateNameBasedUUID(namespace, name, "SHA-1", 5);
}
private static UUID generateNameBasedUUID(String namespace, String name, String algorithm, int version) {
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(namespace.getBytes(StandardCharsets.UTF_8));
md.update(name.getBytes(StandardCharsets.UTF_8));
byte[] hashBytes = md.digest();
hashBytes[6] &= 0x0F; // Clear version
hashBytes[6] |= (version << 4); // Set version
hashBytes[8] &= 0x3F; // Clear variant
hashBytes[8] |= 0x80; // Set variant
return new UUID(bytesToLong(hashBytes, 0), bytesToLong(hashBytes, 8));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Hash algorithm not available: " + algorithm, e);
}
}
private static long bytesToLong(byte[] bytes, int offset) {
long result = 0;
for (int i = 0; i < 8; i++) {
result = (result << 8) | (bytes[offset + i] & 0xFF);
}
return result;
}
public static void main(String[] args) {
// Generate and validate UUIDs for all types
UUID uuid1 = generateUUID1();
UUID uuid3 = generateUUID3("my-namespace", "my-name");
UUID uuid4 = generateUUID4();
UUID uuid5 = generateUUID5("my-namespace", "my-name");
// Print results
System.out.println("UUID1: " + uuid1);
System.out.println("UUID3: " + uuid3);
System.out.println("UUID4: " + uuid4);
System.out.println("UUID5: " + uuid5);
}
}
Output
UUID1: 0000018b-f105-d3b7-0000-88665a4dab02 UUID3: be96d0ea-c5a5-3fcc-b188-e7af3cbac3a7 UUID4: ea800779-1b58-4844-81eb-51a95500ffbb UUID5: 071be3ef-e459-534e-87a9-cc4f96725002
You may like
Implement retry handler for a task in Java
Design an utility class to capture application metrics summary in Java
Utility class to get primitive type from wrapper type and vice versa
FNV hash algorithm implementation in Java
Controlling Randomness in Java: Exploring the Role of Seeds in java.util.Random
Calculating initial capacity from expected size and load factor
No comments:
Post a Comment