看到这篇文章对UUID原理作了比较好的说明,很有帮助
https://blog.youkuaiyun.com/zzhongcy/article/details/114284696
里面的java实现,感觉还有优化的地方,这里用位移的方式来实现一次,耗时可以降低一个数量级,抛出来供大家讨论
package pri.go8;
import lombok.extern.slf4j.Slf4j;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
@Slf4j
public class TestGo8 {
// 注意,这里一共64个值,Z有3个
private static final char[] source = new char[]{'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'Z', 'Z'};
private static final int MOD = source.length - 1;
public static void main(String[] args) {
// 大约800w
final int size = 1 << 23;
UUID[] uuids = new UUID[size];
for (int i = 0; i < size; i++) {
uuids[i] = UUID.randomUUID();
}
System.out.println("by string");
exe(uuids, TestGo8::gen8ByStringBuild);
System.out.println("by bit");
exe(uuids, TestGo8::gen8ByBitMoving);
System.out.println("test scale " + uuids.length);
}
public static void exe(UUID[] uuids, Function<UUID, String> function) {
Set<String> b1 = new HashSet<>(uuids.length);
final long currentTimeMillis = System.currentTimeMillis();
for (int i = 0; i < uuids.length; i++) {
if (!b1.add(function.apply(uuids[i]))) {
log.warn("duplicated!!");
}
}
System.out.println("cost " + (System.currentTimeMillis() - currentTimeMillis));
}
public static String gen8ByStringBuild(UUID uuid) {
StringBuffer shortBuffer = new StringBuffer();
String uuidString = uuid.toString().replace("-", "");
for (int i = 0; i < 8; i++) {
final String str = uuidString.substring(i * 4, i * 4 + 4);
final int x = Integer.parseInt(str, 16);
// 0x3E是62,source最后的Z重复了,不会影响这里的逻辑
shortBuffer.append(source[x % 0x3E]);
}
return shortBuffer.toString();
}
public static String gen8ByBitMoving(UUID uuid) {
// long类型占64位
final long mostSignificantBits = uuid.getMostSignificantBits();
final long leastSignificantBits = uuid.getLeastSignificantBits();
char[] result = new char[8];
result[0] = source[(int) (hash(mostSignificantBits >>> 48) & MOD)];
result[1] = source[(int) (hash(mostSignificantBits << 16 >>> 16 >> 32) & MOD)];
result[2] = source[(int) (hash(mostSignificantBits << 32 >>> 32 >> 16) & MOD)];
result[3] = source[(int) (hash(mostSignificantBits << 48 >>> 48) & MOD)];
result[4] = source[(int) (hash(leastSignificantBits >>> 48) & MOD)];
result[5] = source[(int) (hash(leastSignificantBits << 16 >>> 16 >> 32) & MOD)];
result[6] = source[(int) (hash(leastSignificantBits << 32 >>> 32 >> 16) & MOD)];
result[7] = source[(int) (hash(leastSignificantBits << 48 >>> 48) & MOD)];
return new String(result);
}
private static long hash(long input) {
return input ^ (input >>> 32);
}
}
执行结果,我的CPU是i5-8259U
by string
cost 21610
by bit
cost 3908
test scale 8388608
多执行几次的话,差距不大,也没有出现重复的结果