我需要一个非常紧凑的 UUID,越短越好。
为此,我写道:
public String getBase36UIID() {
// More compact version of UUID
String strUUID = UUID.randomUUID().toString().replace("-", "");
return new BigInteger(strUUID, 16).toString(36);
}
通过执行此代码,我得到,例如:5luppaye6086d5wp4fqyz57xb
这很好,但不是最好的。 Base 36 使用所有数字和小写字母,但不使用大写字母。如果可以使用大写字母作为与小写字母分开的数字,则有可能将数字基数 62 理论化,由这些数字组成:
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
我还可以使用重音字符(例如“è”或“é”)或特殊字符(例如“$”或“!”)来理论化数字基数,从而进一步增加可用数字的数量。然而,使用这些重音或特殊字符可能会给我带来问题,所以目前我不想考虑它们。
在所有这些前提之后,我怎样才能将代表我的 UUID 的 BigInteger 转换为上面理论化的基数 62,以使其更加紧凑?谢谢
我已经验证过像下面这样的代码不可用,因为每个超过 36 的基数都被视为基数 10:
return new BigInteger(strUUID, 16).toString(62);
毕竟,在数学中没有我想象的基数 62,但我想在 Java 中可以创建它。
最佳答案
将数字转换为任意基数的通用算法基于除以余数。
您首先将数字除以基数。余数为您提供数字的最后一位 - 您将其映射到一个符号。如果商不为零,则将其除以底数。余数为您提供倒数第二个数字。然后你用商重复这个过程。
在 Java 中,使用 BigInteger:
String toBase62(BigInteger number) {
String symbols = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
BigInteger base = BigInteger.valueOf(symbols.length());
StringBuilder result = new StringBuilder();
do {
BigInteger[] quotientAndRemainder = number.divideAndRemainder(base);
number = quotientAndRemainder[0];
result.append(symbols.charAt(quotientAndRemainder[1].intValue()));
} while (number.compareTo(BigInteger.ZERO) > 0);
return result.reverse().toString();
}
你需要标识符是 UUID 吗?难道它不能只是任何随机的字母和数字序列吗?如果这是可以接受的,您就不必处理基于数字的转换。String randomString(int length) {
String symbols = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random rnd = new Random();
StringBuilder str = new StringBuilder();
for (int i = 0; i < length; i++) {
str.append(symbols.charAt(rnd.nextInt(symbols.length())));
}
return str.toString();
}
关于java - 极其紧凑的 UUID(使用所有字母数字字符),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63457605/