【开源之夏】新增UUIDv7的生成器

This commit is contained in:
Looly 2024-09-29 09:27:25 +08:00
parent f0c591a1b1
commit 876a69e8c2
2 changed files with 18 additions and 16 deletions

View File

@ -185,18 +185,20 @@ public class UUID implements java.io.Serializable, Comparable<UUID> {
}
/**
* 获取随机生成的UUIDv7
* 获取随机生成的UUIDv7<br>
* 开源之夏贡献内容https://gitee.com/dromara/hutool/pulls/1263
*
* @return UUIDv7
* @author Cason(https://gitee.com/Casonhqc)
*/
public static UUID randomUUID7() {
byte[] randomBytes = new byte[16];
final byte[] randomBytes = new byte[16];
final Random ng = Holder.NUMBER_GENERATOR;
ng.nextBytes(randomBytes);
long[] v7Time = getV7Time();
long milli = v7Time[0];
long seq = v7Time[1];
final long[] v7Time = getV7Time();
final long milli = v7Time[0];
final long seq = v7Time[1];
randomBytes[0] = (byte) (milli >> 40);
randomBytes[1] = (byte) (milli >> 32);
@ -208,20 +210,20 @@ public class UUID implements java.io.Serializable, Comparable<UUID> {
randomBytes[6] = (byte) ((0x70) | (0x0F & (seq >> 8)));
randomBytes[7] = (byte) seq;
randomBytes[8] &= 0x3f; /* clear variant */
randomBytes[8] |= 0x80; /* set to IETF variant */
randomBytes[8] |= (byte) 0x80; /* set to IETF variant */
return new UUID(ByteUtil.toLong(randomBytes, 0, ByteOrder.BIG_ENDIAN),
ByteUtil.toLong(randomBytes, 8, ByteOrder.BIG_ENDIAN));
}
private static long[] getV7Time() {
long nano = System.nanoTime();
final long nano = System.nanoTime();
long milli = nano / NANOS_PER_MILLI;
long seq = (nano - milli * NANOS_PER_MILLI) >> 8;
long now = (milli << 12) + seq;
while (true) {
long last = lastV7time.get();
final long last = lastV7time.get();
if (now <= last) {
now = last + 1;
milli = now >> 12;

View File

@ -31,7 +31,6 @@ import org.junit.jupiter.api.Test;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import static org.junit.jupiter.api.Assertions.*;
@ -79,7 +78,7 @@ public class IdUtilTest {
timer.start();
for (int i = 0; i < 1000000; i++) {
//noinspection ResultOfMethodCallIgnored
UUID.randomUUID().toString().replace("-", "");
java.util.UUID.randomUUID().toString().replace("-", "");
}
timer.stop();
Console.log(timer.getLastTaskTimeMillis());
@ -169,8 +168,8 @@ public class IdUtilTest {
@Test
public void testUUIDv7Format() {
org.dromara.hutool.core.data.id.UUID uuid = org.dromara.hutool.core.data.id.UUID.randomUUID7();
String uuidStr = uuid.toString();
final org.dromara.hutool.core.data.id.UUID uuid = org.dromara.hutool.core.data.id.UUID.randomUUID7();
final String uuidStr = uuid.toString();
// 验证UUID字符串格式是否符合标准
assertTrue(uuidStr.matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"));
@ -178,7 +177,7 @@ public class IdUtilTest {
@Test
public void testUUIDv7Properties() {
org.dromara.hutool.core.data.id.UUID uuid = org.dromara.hutool.core.data.id.UUID.randomUUID7();
final org.dromara.hutool.core.data.id.UUID uuid = org.dromara.hutool.core.data.id.UUID.randomUUID7();
// 验证版本号是否为7
assertEquals(7, uuid.version());
@ -190,11 +189,11 @@ public class IdUtilTest {
@RepeatedTest(10)
public void testUUIDv7Uniqueness() {
Set<org.dromara.hutool.core.data.id.UUID> uuids = new HashSet<>();
final Set<org.dromara.hutool.core.data.id.UUID> uuids = new HashSet<>();
// 生成100万个UUIDv7验证是否有重复
for (int i = 0; i < 1000000; i++) {
org.dromara.hutool.core.data.id.UUID uuid = org.dromara.hutool.core.data.id.UUID.randomUUID7();
final org.dromara.hutool.core.data.id.UUID uuid = org.dromara.hutool.core.data.id.UUID.randomUUID7();
assertFalse(uuids.contains(uuid));
uuids.add(uuid);
}
@ -207,7 +206,7 @@ public class IdUtilTest {
// 验证连续生成的1000个UUIDv7是否呈单调递增趋势
for (int i = 0; i < 1000; i++) {
org.dromara.hutool.core.data.id.UUID next = org.dromara.hutool.core.data.id.UUID.randomUUID7();
final org.dromara.hutool.core.data.id.UUID next = org.dromara.hutool.core.data.id.UUID.randomUUID7();
assertTrue(next.compareTo(prev) > 0);
prev = next;
}
@ -217,6 +216,7 @@ public class IdUtilTest {
* UUIDv7的性能测试
*/
@Test
@Disabled
public void testUUIDv7Benchmark() {
final StopWatch timer = DateUtil.createStopWatch();