JAVA生成短8位UUID

本文探讨了UUID的原理,并分享了一种使用位运算优化的Java实现方式,旨在提高生成短UUID的效率,减少耗时,且经测试未发现重复结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看到这篇文章对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

多执行几次的话,差距不大,也没有出现重复的结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值