Merge pull request #15106 from hangga/generate-unique-long

BAEL-6430 : Generate unique long using UUID | Hangga Aji Sayekti
This commit is contained in:
Liam Williams 2023-11-27 01:03:23 +00:00 committed by GitHub
commit da3f32c737
3 changed files with 127 additions and 2 deletions

View File

@ -0,0 +1,83 @@
package com.baeldung.uuid;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.UUID;
/**
* Methods are called by reflection in the unit test
*/
@SuppressWarnings("unused")
public class UUIDPositiveLongGenerator {
public long getLeastSignificantBits() {
return Math.abs(UUID.randomUUID().getLeastSignificantBits());
}
public long getMostSignificantBits() {
return Math.abs(UUID.randomUUID().getMostSignificantBits());
}
public long combineByteBuffer() {
UUID uuid = UUID.randomUUID();
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
bb.rewind();
return Math.abs(bb.getLong());
}
public long combineBitwise() {
UUID uniqueUUID = UUID.randomUUID();
long mostSignificantBits = uniqueUUID.getMostSignificantBits();
long leastSignificantBits = uniqueUUID.getLeastSignificantBits();
return Math.abs((mostSignificantBits << 32) | (leastSignificantBits & 0xFFFFFFFFL));
}
public long combineDirect() {
UUID uniqueUUID = UUID.randomUUID();
long mostSignificantBits = uniqueUUID.getMostSignificantBits();
long leastSignificantBits = uniqueUUID.getLeastSignificantBits();
return Math.abs(mostSignificantBits ^ (leastSignificantBits >> 1));
}
public long combinePermutation() {
UUID uuid = UUID.randomUUID();
long mostSigBits = uuid.getMostSignificantBits();
long leastSigBits = uuid.getLeastSignificantBits();
byte[] uuidBytes = new byte[16];
for (int i = 0; i < 8; i++) {
uuidBytes[i] = (byte) (mostSigBits >>> (8 * (7 - i)));
uuidBytes[i + 8] = (byte) (leastSigBits >>> (8 * (7 - i)));
}
long result = 0;
for (byte b : uuidBytes) {
result = (result << 8) | (b & 0xFF);
}
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));
}
}

View File

@ -0,0 +1,43 @@
package com.baeldung.uuid;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
public class UUIDPositiveLongGeneratorUnitTest {
private final UUIDPositiveLongGenerator uuidLongGenerator = new UUIDPositiveLongGenerator();
private final Set<Long> uniqueValues = new HashSet<>();
@Test
void whenForeachMethods_thenRetryWhileNotUnique() throws Exception {
for (Method method : uuidLongGenerator.getClass().getDeclaredMethods()) {
long uniqueValue;
do uniqueValue = (long) method.invoke(uuidLongGenerator); while (!isUnique(uniqueValue));
assertThat(uniqueValue).isPositive();
}
}
@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);
}
}

View File

@ -2,8 +2,7 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>