22位/32位UUID
32 位 UUID 优化建议
32 位的 UUID,最常见的代码:UUID.randomUUID().toString().replace("-",""),
有野心的程序员,追求极致性能的话,会选择优化这一段代码,
可以使用 Long.toHexString(),只是过程需要注意:1L 的 16 进制数也是1,不满足 32 位的要补0;
22 位 UUID 基本原理
22 位 UUID,就是将 128 位的 2 进制的 UUID 转为 64 进制,实现进制转换函数即可。
源码
/*
* MIT License
*
* Copyright (c) 2019 Mr.css
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package cn.seaboot.commons.core;
import cn.seaboot.commons.digest.Base64;
import java.util.UUID;
/**
* 设备号
*
* @author ChenSS 2018年7月13日 上午11:20:38
*/
public class UUIDUtils {
private UUIDUtils() {
}
/**
* 生成UUID
*
* @return uuid
*/
public static String genUUID() {
return UUID.randomUUID().toString();
}
/**
* 生成 32 位 UUID
*
* <p>
* Returns a {@code String} object representing this {@code UUID}.
*
* <p> The UUID string representation is as described by this BNF:
* <blockquote><pre>
* {@code
* UUID = <time_low><time_mid>
* <time_high_and_version>
* <variant_and_sequence>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit =
* "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
* | "a" | "b" | "c" | "d" | "e" | "f"
* | "A" | "B" | "C" | "D" | "E" | "F"
* }</pre></blockquote>
*
* @return A string representation of this {@code UUID}
*/
public static String genUUID32() {
UUID uuid = UUID.randomUUID();
long mostSigBits = uuid.getMostSignificantBits();
long leastSigBits = uuid.getLeastSignificantBits();
return (digits(mostSigBits >> 32) +
digits(mostSigBits) +
digits(leastSigBits >> 32) +
digits(leastSigBits));
}
/**
* 二进制 1 后面跟 32 个 0
*/
private static final long HI = 1L << (8 * 4);
/**
* Returns val represented by the specified number of hex digits.
*/
private static String digits(long val) {
long hi = HI;
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}
/**
* 生成32位UUID
* <p>
* 如果仅用于生成32为UUID,更优的函数是{@link #genUUID32()}
* <p>
* 此函数用于{@link UUID#toString()}结果的转换。
* <p>
* old version:
* uuid.substring(0, 8) + uuid.substring(9, 13) + uuid.substring(14, 18) + uuid.substring(19, 23) + uuid.substring(24)
* <p>
* 执行效率与历史版本性基本一致,新版代码减少了创建对象的次数。
*
* @return uuid
*/
public static String toUUID32(String uuid) {
StringBuilder sb = new StringBuilder(32);
char ch;
for (int i = 0; i < uuid.length(); i++) {
ch = uuid.charAt(i);
if (ch != '-') {
sb.append(ch);
}
}
return sb.toString();
}
/**
* 生成 22 位 UUID
* <p>
* base64 算法:8 位二进制数,转为 1 个字节,128 位正好 16 字节,
* 16 字节产生 24位 base64 字符串,去除占位 2 个字母,正好 22 位。
*
* @return uuid
*/
public static String base64UUID() {
UUID uuid = UUID.randomUUID();
long msb = uuid.getMostSignificantBits();
long lsb = uuid.getLeastSignificantBits();
int x;
byte[] buffer = new byte[16];
for (int i = 0; i < 8; i++) {
x = 8 * (7 - i);
buffer[i] = (byte) (int) (msb >> x);
buffer[i + 8] = (byte) (int) (lsb >> x);
}
return Base64.encodeString(buffer).substring(0, 22);
}
/**
* 生成 22 位 UUID
* <p>
* UUID 128位,每 6 位用一个 64 进制字符表示,正好 22 位。
* 此函数采用的是 64 进制转换,而不是 Base64 编码,因为 128 不能被 6 整除,第 11 位和第 22 位,只能是字母。
* <p>
* 将数字转为
*
* @return uuid
*/
public static String genUUID22() {
UUID uuid = UUID.randomUUID();
long msb = uuid.getMostSignificantBits();
long lsb = uuid.getLeastSignificantBits();
int x;
char[] buffer = new char[22];
for (int i = 0; i < 11; i++) {
x = 6 * (10 - i);
buffer[i] = digits64((int) (msb >> x));
buffer[i + 11] = digits64((int) (lsb >> x));
}
return new String(buffer);
}
/**
* Returns val represented by the specified number of 64 digits.
*/
private static char digits64(int val) {
return CHARS[val & 63];
}
/**
* 生成 8 位 UUID 标识码
* <p>
* 作为唯一 ID 使用的时候,很明显,长度不够,必定会出现重复,
* 但是可以作为 uuid 的标识码使用,类似于数字签名,如果 uuid 被篡改,生成的标识码会发生变化。
*
* @param uid 32 位 uuid
* @return uuid 标识码
*/
public static String toUUID8(String uid) {
StringBuilder shortBuffer = new StringBuilder();
for (int i = 0; i < 8; i++) {
String str = uid.substring(i * 4, i * 4 + 4);
int x = Integer.parseInt(str, 16);
shortBuffer.append(CHARS[x & 61]);
}
return shortBuffer.toString();
}
private final static char[] CHARS = {'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', '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', '+', '/'};
}
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!