mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
【开源之夏】新增UUIDv7的生成器
This commit is contained in:
parent
f0c591a1b1
commit
876a69e8c2
@ -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
|
* @return UUIDv7
|
||||||
|
* @author Cason(https://gitee.com/Casonhqc)
|
||||||
*/
|
*/
|
||||||
public static UUID randomUUID7() {
|
public static UUID randomUUID7() {
|
||||||
byte[] randomBytes = new byte[16];
|
final byte[] randomBytes = new byte[16];
|
||||||
final Random ng = Holder.NUMBER_GENERATOR;
|
final Random ng = Holder.NUMBER_GENERATOR;
|
||||||
ng.nextBytes(randomBytes);
|
ng.nextBytes(randomBytes);
|
||||||
|
|
||||||
long[] v7Time = getV7Time();
|
final long[] v7Time = getV7Time();
|
||||||
long milli = v7Time[0];
|
final long milli = v7Time[0];
|
||||||
long seq = v7Time[1];
|
final long seq = v7Time[1];
|
||||||
|
|
||||||
randomBytes[0] = (byte) (milli >> 40);
|
randomBytes[0] = (byte) (milli >> 40);
|
||||||
randomBytes[1] = (byte) (milli >> 32);
|
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[6] = (byte) ((0x70) | (0x0F & (seq >> 8)));
|
||||||
randomBytes[7] = (byte) seq;
|
randomBytes[7] = (byte) seq;
|
||||||
randomBytes[8] &= 0x3f; /* clear variant */
|
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),
|
return new UUID(ByteUtil.toLong(randomBytes, 0, ByteOrder.BIG_ENDIAN),
|
||||||
ByteUtil.toLong(randomBytes, 8, ByteOrder.BIG_ENDIAN));
|
ByteUtil.toLong(randomBytes, 8, ByteOrder.BIG_ENDIAN));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long[] getV7Time() {
|
private static long[] getV7Time() {
|
||||||
long nano = System.nanoTime();
|
final long nano = System.nanoTime();
|
||||||
long milli = nano / NANOS_PER_MILLI;
|
long milli = nano / NANOS_PER_MILLI;
|
||||||
long seq = (nano - milli * NANOS_PER_MILLI) >> 8;
|
long seq = (nano - milli * NANOS_PER_MILLI) >> 8;
|
||||||
long now = (milli << 12) + seq;
|
long now = (milli << 12) + seq;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
long last = lastV7time.get();
|
final long last = lastV7time.get();
|
||||||
if (now <= last) {
|
if (now <= last) {
|
||||||
now = last + 1;
|
now = last + 1;
|
||||||
milli = now >> 12;
|
milli = now >> 12;
|
||||||
|
@ -31,7 +31,6 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
@ -79,7 +78,7 @@ public class IdUtilTest {
|
|||||||
timer.start();
|
timer.start();
|
||||||
for (int i = 0; i < 1000000; i++) {
|
for (int i = 0; i < 1000000; i++) {
|
||||||
//noinspection ResultOfMethodCallIgnored
|
//noinspection ResultOfMethodCallIgnored
|
||||||
UUID.randomUUID().toString().replace("-", "");
|
java.util.UUID.randomUUID().toString().replace("-", "");
|
||||||
}
|
}
|
||||||
timer.stop();
|
timer.stop();
|
||||||
Console.log(timer.getLastTaskTimeMillis());
|
Console.log(timer.getLastTaskTimeMillis());
|
||||||
@ -169,8 +168,8 @@ public class IdUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUUIDv7Format() {
|
public void testUUIDv7Format() {
|
||||||
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();
|
||||||
String uuidStr = uuid.toString();
|
final String uuidStr = uuid.toString();
|
||||||
|
|
||||||
// 验证UUID字符串格式是否符合标准
|
// 验证UUID字符串格式是否符合标准
|
||||||
assertTrue(uuidStr.matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"));
|
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
|
@Test
|
||||||
public void testUUIDv7Properties() {
|
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
|
// 验证版本号是否为7
|
||||||
assertEquals(7, uuid.version());
|
assertEquals(7, uuid.version());
|
||||||
@ -190,11 +189,11 @@ public class IdUtilTest {
|
|||||||
|
|
||||||
@RepeatedTest(10)
|
@RepeatedTest(10)
|
||||||
public void testUUIDv7Uniqueness() {
|
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,验证是否有重复
|
// 生成100万个UUIDv7,验证是否有重复
|
||||||
for (int i = 0; i < 1000000; i++) {
|
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));
|
assertFalse(uuids.contains(uuid));
|
||||||
uuids.add(uuid);
|
uuids.add(uuid);
|
||||||
}
|
}
|
||||||
@ -207,7 +206,7 @@ public class IdUtilTest {
|
|||||||
|
|
||||||
// 验证连续生成的1000个UUIDv7是否呈单调递增趋势
|
// 验证连续生成的1000个UUIDv7是否呈单调递增趋势
|
||||||
for (int i = 0; i < 1000; i++) {
|
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);
|
assertTrue(next.compareTo(prev) > 0);
|
||||||
prev = next;
|
prev = next;
|
||||||
}
|
}
|
||||||
@ -217,6 +216,7 @@ public class IdUtilTest {
|
|||||||
* UUIDv7的性能测试
|
* UUIDv7的性能测试
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled
|
||||||
public void testUUIDv7Benchmark() {
|
public void testUUIDv7Benchmark() {
|
||||||
final StopWatch timer = DateUtil.createStopWatch();
|
final StopWatch timer = DateUtil.createStopWatch();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user