zoukankan      html  css  js  c++  java
  • 更短且不失高效的UUID生成算法

    Java原生的UUID长度为36位,嫌长
    这里自己实现了一套自己的算法,来生成较短的UUID

    由雪花算法启发而来,
    大致原理是利用时间戳+随机值做值,然后转换成62进制(当然这个进制数你也可以搞成更多)

    有一些参数可以控制一些行为,都在注释里了

    你可以自己修改digits数组,乱乱序啥的,混淆一下,随机性可能更好一些

    /**
     * Java 原生的UUID为36位 or 32位,太长. 这里提供一个位数较短的UUID.
     * <p>
     * UUID生成规则,当前时间减去'零时'的毫秒数 + N位随机数,转变成62进制的String类型.
     * <p>
     * 当前配置可满足30年内每毫秒10^9分之一的碰撞.
     * <p>
     * 实测现在长度为13位,想要更短的话可以调整下方的几个参数
     *
     * @author libing02 , on 11月 20, 2019.
     */
    public class ShortUUID {
    
        /**
         * digits还可以扩,但是不要包含下面的SEPARATOR
         * <p>
         * 也可以替换一个"乱序"digits排列,最终使uuid看起来不是有序的.
         * <p>
         * 一旦用到生产环境,digits就不要再变动了,否则会出现重复
         * <p>
         */
        private static final char[] digits = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
            .toCharArray();
    
        private static final char SEPARATOR = '_';
    
        // 2019-11-15 17:00:00
        private static final long ERA_TIME = 1573808400000L;
    
        // UUID一次轮回的指数. 12则为大概30年左右,11则为3年左右. 13就是300年
        private static final int TIME_LOOP_INDEX = 12;
    
        // 碰撞指数.毫秒下万万分之一
        private static final int COLLISION_INDEX = 99999999;
    
        private static final boolean MIX_UP = true;
    
        public static String randomUUID() {
            long passTime = System.currentTimeMillis() - ERA_TIME;
    
            long l = passTime;
            // 反转主要是为了让uuid看起来不是递增的
            // 但这也会导致出现极小概率不同时间的碰撞,所以建议优先选择不反转
            if (MIX_UP) {
                StringBuilder stringBuilder = new StringBuilder(String.valueOf(passTime)).reverse();
                while (stringBuilder.length() < TIME_LOOP_INDEX) {
                    stringBuilder.append('0');
                }
                l = Long.parseLong(stringBuilder.substring(0, TIME_LOOP_INDEX));
            }
    
            return baseConversion(l, digits.length) + SEPARATOR +
                baseConversion(RandomUtils.ranInt(COLLISION_INDEX), digits.length);
        }
    
        @Test
        public void test() {
            System.out.println(randomUUID());
        }
    
    
        /**
         * 将10进制转换成任意进制,照着Long原生的进制转换写的,原生最大支持到32进制
         * <p>
         * 这里支持到更高进制,可以扩展digits数组实现更高
         *
         * @param i     十进制Long型
         * @param radix 进制,[2-62]
         * @return 转换后的String
         */
        public static String baseConversion(long i, int radix) {
            if (radix < 2 || radix > digits.length) {
                radix = 10;
            }
    
            int charPos = digits.length * 2;
            final int size = charPos + 1;
    
            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));
        }
    }
    
  • 相关阅读:
    PHP调试的时候出现了警告:
    快报滚动
    js foreach、map函数
    箭头函数和普通函数的区别
    flex布局
    react+propTypes
    手机尺寸
    less的使用
    发现是在IE6-IE9下,下列元素table,thead,tfoot,tbody,tr,col,colgroup,html,title,style,frameset的innerHTML属性是只读的
    div+css 组织结构
  • 原文地址:https://www.cnblogs.com/acbingo/p/11900317.html
Copyright © 2011-2022 走看看