diff --git a/core-java-modules/core-java-uuid/src/main/java/com/baeldung/uuid/UUIDPositiveLongGenerator.java b/core-java-modules/core-java-uuid/src/main/java/com/baeldung/uuid/UUIDPositiveLongGenerator.java index 13b32be856..eb3a511256 100644 --- a/core-java-modules/core-java-uuid/src/main/java/com/baeldung/uuid/UUIDPositiveLongGenerator.java +++ b/core-java-modules/core-java-uuid/src/main/java/com/baeldung/uuid/UUIDPositiveLongGenerator.java @@ -1,6 +1,7 @@ package com.baeldung.uuid; import java.nio.ByteBuffer; +import java.security.SecureRandom; import java.util.UUID; /** @@ -16,10 +17,6 @@ public class UUIDPositiveLongGenerator { return Math.abs(UUID.randomUUID().getMostSignificantBits()); } - public long getHashCode() { - return Math.abs(UUID.randomUUID().toString().hashCode()); - } - public long combineByteBuffer() { UUID uuid = UUID.randomUUID(); ByteBuffer bb = ByteBuffer.wrap(new byte[16]); @@ -30,9 +27,10 @@ public class UUIDPositiveLongGenerator { } public long combineBitwise() { - UUID uniqueUUID; - uniqueUUID = UUID.randomUUID(); - return Math.abs((uniqueUUID.getMostSignificantBits() << 32) | (uniqueUUID.getLeastSignificantBits() & 0xFFFFFFFFL)); + UUID uniqueUUID = UUID.randomUUID(); + long mostSignificantBits = uniqueUUID.getMostSignificantBits(); + long leastSignificantBits = uniqueUUID.getLeastSignificantBits(); + return Math.abs((mostSignificantBits << 32) | (leastSignificantBits & 0xFFFFFFFFL)); } public long combineDirect() { @@ -59,4 +57,27 @@ public class UUIDPositiveLongGenerator { } return Math.abs(result); } + + public long combineWithSecureRandom() { + UUID uniqueUUID = UUID.randomUUID(); + SecureRandom secureRandom = new SecureRandom(); + long randomBits = secureRandom.nextLong(); + + long mostSignificantBits = uniqueUUID.getMostSignificantBits() ^ randomBits; + long leastSignificantBits = uniqueUUID.getLeastSignificantBits(); + + return Math.abs((mostSignificantBits << 32) | (leastSignificantBits & 0xFFFFFFFFL)); + } + + public long combineWithNanoTime() { + UUID uniqueUUID = UUID.randomUUID(); + long nanoTime = System.nanoTime(); + + long mostSignificantBits = uniqueUUID.getMostSignificantBits() ^ nanoTime; + long leastSignificantBits = uniqueUUID.getLeastSignificantBits(); + + return Math.abs((mostSignificantBits << 32) | (leastSignificantBits & 0xFFFFFFFFL)); + } + + } diff --git a/core-java-modules/core-java-uuid/src/test/java/com/baeldung/uuid/UUIDPositiveLongGeneratorUnitTest.java b/core-java-modules/core-java-uuid/src/test/java/com/baeldung/uuid/UUIDPositiveLongGeneratorUnitTest.java index fab07df2a0..a4d57b19c2 100644 --- a/core-java-modules/core-java-uuid/src/test/java/com/baeldung/uuid/UUIDPositiveLongGeneratorUnitTest.java +++ b/core-java-modules/core-java-uuid/src/test/java/com/baeldung/uuid/UUIDPositiveLongGeneratorUnitTest.java @@ -1,52 +1,43 @@ package com.baeldung.uuid; import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.lang.reflect.Method; -import java.text.DecimalFormat; import java.util.HashSet; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; public class UUIDPositiveLongGeneratorUnitTest { - private final static int NUMBER_OF_CHECKS = 1000000; - private final static double COLLISION_THRESHOLD = 0.001; + private final UUIDPositiveLongGenerator uuidLongGenerator = new UUIDPositiveLongGenerator(); - private final Logger logger = LoggerFactory.getLogger(UUIDPositiveLongGeneratorUnitTest.class); + + private final Set uniqueValues = new HashSet<>(); @Test - void whenForeachGenerateLongValue_thenCollisionsCheck() throws Exception { - printTableHeader(); + void whenForeachMethods_thenRetryWhileNotUnique() throws Exception { for (Method method : uuidLongGenerator.getClass().getDeclaredMethods()) { - collisionCheck(method); - } - } - - private void printTableHeader() { - logger.info(String.format("%-30s %-15s %-15s", "Approach(method name)", "collisions", "probability")); - logger.info("-----------------------------------------------------------------------"); - } - - private void printOutput(String method, int collisionsCount, double collisionsProbability) { - DecimalFormat decimalFormat = new DecimalFormat("#.#####"); - logger.info(String.format("%-30s %-15s %-15s", method, collisionsCount, decimalFormat.format(collisionsProbability))); - } - - private void collisionCheck(Method method) throws Exception { - Set uniqueValues = new HashSet<>(); - int collisions = 0; - for (int i = 0; i < NUMBER_OF_CHECKS; i++) { - long uniqueValue = (long) method.invoke(uuidLongGenerator); + long uniqueValue; + do uniqueValue = (long) method.invoke(uuidLongGenerator); while (!isUnique(uniqueValue)); assertThat(uniqueValue).isPositive(); - if (!uniqueValues.add(uniqueValue)) { - collisions++; - } } - double collisionsProbability = (double) collisions / NUMBER_OF_CHECKS; - printOutput(method.getName(), collisions, collisionsProbability); - assertThat(collisionsProbability).isLessThan(COLLISION_THRESHOLD); } + + @Test + void whenGivenLongValue_thenCheckUniqueness() { + long uniqueValue = generateUniqueLong(); + assertThat(uniqueValue).isPositive(); + } + + private long generateUniqueLong() { + long uniqueValue; + do uniqueValue = uuidLongGenerator.combineBitwise(); while (!isUnique(uniqueValue)); + return uniqueValue; + } + + private boolean isUnique(long value) { + // Implement uniqueness checking logic, for example, by checking in the database + return uniqueValues.add(value); + } + }