Shorter and yet efficient generation algorithm UUID

package com.fenbi.orion.notifypush.server.util;

import com.fenbi.common.util.RandomUtils;

/**
 * Java 原生的UUID为36位 or 32位,太长.
 * 这里提供一个位数较短的UUID.
 * <p>
 * UUID生成规则,当前时间减去'纪元时间'的毫秒数 + 三位随机数生成的long,转变成62进制的String类型.
 * <p>
 * 当前配置可满足3年内每毫秒千分之一的碰撞.可以修改配置实现更久or更大的碰撞。
 * <p>
 * 实测长度8位
 *
 * @author libing02 , on 11月 20, 2019.
 */
public class ShortUUID {

    private static final char[] digits = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

    // 2019-11-15 17:00:00
    private static final long ERA_TIME = 1573808400000L;

    // UUID一次轮回的指数. 12则为大概30年左右,11则为3年左右. 业务逻辑短时间内唯一即可
    private static final int TIME_LOOP_INDEX = 11;

    // 碰撞指数.毫秒下千分之一够用了
    private static final int COLLISION_INDEX = 999;

    public static String randomUUID() {
        long passTime = System.currentTimeMillis() - ERA_TIME;

        // 反转后右补0
        StringBuilder stringBuilder = new StringBuilder(String.valueOf(passTime)).reverse();
        while (stringBuilder.length() < TIME_LOOP_INDEX) {
            stringBuilder.append('0');
        }
        long l = Long.parseLong(stringBuilder.substring(0, TIME_LOOP_INDEX));

        return toString(l, digits.length) + toString(RandomUtils.ranInt(COLLISION_INDEX), digits.length);
    }

    /**
     * 将10进制转换成任意进制,
     * 照着Long原生的进制转换写的,原生最大支持到32进制,这里支持到62进制,理论上可以扩展digits数组实现更高
     */
    public static String toString(long i, int radix) {
        if (radix < 2 || radix > digits.length) {
            radix = 10;
        }
        if (radix <= 32) {
            return Long.toString(i, radix);
        }

        final int size = 65;
        int charPos = 64;

        char[] buf = new char[size];
        boolean negative = (i < 0);

        if (!negative) {
            i = -i;
        }

        while (i <= -radix) {
            buf[charPos--] = digits[(int) (-(i % radix))];
            i = i / radix;
        }
        buf[charPos] = digits[(int) (-i)];

        if (negative) {
            buf[--charPos] = '-';
        }

        return new String(buf, charPos, (size - charPos));
    }
}

Guess you like

Origin www.cnblogs.com/acbingo/p/11900317.html