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));
}
}