This commit is contained in:
Looly 2024-03-15 17:35:00 +08:00
parent 9a3d6857db
commit b5cd26822e
4 changed files with 166 additions and 33 deletions

View File

@ -52,36 +52,36 @@ public class Number128 extends Number implements Comparable<Number128>{
}
/**
* 获取高位值
* 获取最高有效位Most Significant Bit64 bit8 bytes
*
* @return 高位值
* @return 最高有效位Most Significant Bit64 bit8 bytes
*/
public long getMostSigBits() {
return mostSigBits;
}
/**
* 设置高位值
* 设置最高有效位Most Significant Bit64 bit8 bytes
*
* @param hiValue 高位值
* @param hiValue 最高有效位Most Significant Bit64 bit8 bytes
*/
public void setMostSigBits(final long hiValue) {
this.mostSigBits = hiValue;
}
/**
* 获取低位值
* 获取最低有效位Least Significant Bit64 bit8 bytes
*
* @return 地位值
* @return 最低有效位Least Significant Bit64 bit8 bytes
*/
public long getLeastSigBits() {
return leastSigBits;
}
/**
* 设置低位值
* 设置最低有效位Least Significant Bit64 bit8 bytes
*
* @param leastSigBits 低位值
* @param leastSigBits 最低有效位Least Significant Bit64 bit8 bytes
*/
public void setLeastSigBits(final long leastSigBits) {
this.leastSigBits = leastSigBits;

View File

@ -21,6 +21,7 @@ import org.dromara.hutool.core.util.RandomUtil;
import java.io.Serializable;
import java.nio.ByteOrder;
import java.util.Objects;
import java.util.Random;
/**
* 参考https://github.com/zjcscut/framework-mesh/blob/master/ulid4j/src/main/java/cn/vlts/ulid/ULID.java
@ -51,10 +52,68 @@ public class ULID implements Comparable<ULID>, Serializable {
private static final long OVERFLOW = 0x0000000000000000L;
// region ----- Factory methods
/**
* 创建一个新的ULID使用当前系统时间戳和随机数
*
* @return ULID
*/
public static ULID of() {
return of(System.currentTimeMillis(), RandomUtil.randomBytes(RANDOMNESS_BYTE_LEN));
return of(System.currentTimeMillis());
}
/**
* 创建一个新的ULID使用指定系统时间戳和随机数
*
* @param timestamp 时间戳
* @return ULID
*/
public static ULID of(final long timestamp) {
return of(timestamp, RandomUtil.getRandom());
}
/**
* 创建一个新的ULID使用指定系统时间戳和指定随机对象
*
* @param timestamp 时间戳
* @param random {@link Random}
* @return ULID
*/
public static ULID of(final long timestamp, final Random random) {
return of(timestamp, RandomUtil.randomBytes(RANDOMNESS_BYTE_LEN, random));
}
/**
* 创建一个新的ULID使用指定系统时间戳和指定填充数
*
* @param timestamp 时间戳
* @param randomness 指定填充数
* @return ULID
*/
public static ULID of(final long timestamp, final byte[] randomness) {
// 时间戳最多为48 bit(6 bytes)
checkTimestamp(timestamp);
Assert.notNull(randomness);
// 随机数部分长度必须为80 bit(10 bytes)
Assert.isTrue(RANDOMNESS_BYTE_LEN == randomness.length, "Invalid randomness");
long msb = 0;
// 时间戳左移16位低位补零准备填入部分随机数位即16_bit_uint_random
msb |= timestamp << 16;
// randomness[0]左移0位填充到16_bit_uint_random的高8位randomness[1]填充到16_bit_uint_random的低8位
msb |= (long) (randomness[0x0] & 0xff) << 8;
// randomness[1]填充到16_bit_uint_random的低8位
msb |= randomness[0x1] & 0xff;
return new ULID(new Number128(ByteUtil.toLong(randomness, 2, ByteOrder.BIG_ENDIAN), msb));
}
/**
* 解析一个Crockford`s Base32的ULID
*
* @param ulidString Crockford`s Base32的ULID
* @return ULID
*/
public static ULID of(final String ulidString) {
Objects.requireNonNull(ulidString, "ulidString must not be null!");
if (ulidString.length() != 26) {
@ -75,6 +134,12 @@ public class ULID implements Comparable<ULID>, Serializable {
return new ULID(new Number128(least, most));
}
/**
* 从bytes解析ULID
*
* @param data bytes
* @return ULID
*/
public static ULID of(final byte[] data) {
Objects.requireNonNull(data, "data must not be null!");
if (data.length != 16) {
@ -91,24 +156,6 @@ public class ULID implements Comparable<ULID>, Serializable {
return new ULID(new Number128(leastSignificantBits, mostSignificantBits));
}
public static ULID of(final long timestamp, final byte[] randomness) {
// 时间戳最多为48 bit(6 bytes)
checkTimestamp(timestamp);
Assert.notNull(randomness);
// 随机数部分长度必须为80 bit(10 bytes)
Assert.isTrue(RANDOMNESS_BYTE_LEN == randomness.length, "Invalid randomness");
long msb = 0;
// 时间戳左移16位低位补零准备填入部分随机数位即16_bit_uint_random
msb |= timestamp << 16;
// randomness[0]左移0位填充到16_bit_uint_random的高8位randomness[1]填充到16_bit_uint_random的低8位
msb |= (long) (randomness[0x0] & 0xff) << 8;
// randomness[1]填充到16_bit_uint_random的低8位
msb |= randomness[0x1] & 0xff;
return new ULID(new Number128(ByteUtil.toLong(randomness, 2, ByteOrder.BIG_ENDIAN), msb));
}
// endregion
private final Number128 idValue;
@ -122,27 +169,37 @@ public class ULID implements Comparable<ULID>, Serializable {
this.idValue = number128;
}
/**
* 获取最高有效位Most Significant Bit64 bit8 bytes
*
* @return 最高有效位Most Significant Bit64 bit8 bytes
*/
public long getMostSignificantBits() {
return this.idValue.getMostSigBits();
}
/**
* 获取最低有效位Least Significant Bit64 bit8 bytes
*
* @return 最低有效位Least Significant Bit64 bit8 bytes
*/
public long getLeastSignificantBits() {
return this.idValue.getLeastSigBits();
}
/**
* Get the timestamp component of ULID
* 获取ULID的时间戳部分
*
* @return the timestamp component
* @return 时间戳
*/
public long getTimestamp() {
return this.idValue.getMostSigBits() >>> 16;
}
/**
* Get the randomness component of ULID
* 获取ULID的随机数部分
*
* @return the randomness component
* @return 随机数部分
*/
public byte[] getRandomness() {
final long msb = this.idValue.getMostSigBits();
@ -156,6 +213,11 @@ public class ULID implements Comparable<ULID>, Serializable {
return randomness;
}
/**
* 自增ULID
*
* @return 返回自增ULID
*/
public ULID increment() {
final long msb = this.idValue.getMostSigBits();
final long lsb = this.idValue.getLeastSigBits();
@ -164,9 +226,27 @@ public class ULID implements Comparable<ULID>, Serializable {
if (newLsb == OVERFLOW) {
newMsb += 1;
}
return new ULID(new Number128(lsb, msb));
return new ULID(new Number128(newLsb, newMsb));
}
/**
* 获取下一个有序的ULID
*
* @param timestamp 时间戳
* @return 如果给定时间戳与当前ULID相同则返回自增ULID否则返回一个新的ULID
*/
public ULID nextMonotonic(final long timestamp) {
if (getTimestamp() == timestamp) {
return increment();
}
return of(timestamp);
}
/**
* 转为bytes值
*
* @return bytes值
*/
public byte[] toBytes() {
final long msb = this.idValue.getMostSigBits();
final long lsb = this.idValue.getLeastSigBits();
@ -181,12 +261,22 @@ public class ULID implements Comparable<ULID>, Serializable {
return result;
}
/**
* 转为UUID
*
* @return UUID
*/
public UUID toUUID() {
final long msb = this.idValue.getMostSigBits();
final long lsb = this.idValue.getLeastSigBits();
return new UUID(msb, lsb);
}
/**
* 转为JDK的UUID
*
* @return UUID
*/
public java.util.UUID toJdkUUID() {
final long msb = this.idValue.getMostSigBits();
final long lsb = this.idValue.getLeastSigBits();

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2023. looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* https://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.core.data.id;
import org.dromara.hutool.core.lang.generator.Generator;
/**
* ULID生成器
*
* @author looly
* @since 6.0.0
*/
public class ULIDGenerator implements Generator<String> {
@Override
public String next() {
return ULID.of().toString();
}
}

View File

@ -186,8 +186,23 @@ public class RandomUtil {
* @return bytes
*/
public static byte[] randomBytes(final int length) {
return randomBytes(length, getRandom());
}
/**
* 随机bytes
*
* @param length 长度
* @param random {@link Random}
* @return bytes
* @since 6.0.0
*/
public static byte[] randomBytes(final int length, Random random) {
if (null == random) {
random = getRandom();
}
final byte[] bytes = new byte[length];
getRandom().nextBytes(bytes);
random.nextBytes(bytes);
return bytes;
}