mysql 压缩uuid长度_UUID不失精度,长度改进

在使用到uuid的时候,往往头疼于它的长度(如1bfe50d8-544e-4e8a-95b8-199ceff15268),于是乎就有了改写uuid的各种方法

1.去除“-”的uuid

不觉得uuid很长,但是就是看着中间的“-”很难受,又占长度,简单直接点就是

UUID uuid = UUID.randomUUID();

uuid.toString.replace("-", "");

额,这种方法,简单粗暴不优雅,其实呢,还可以看看这个“-”是哪里来的:

public String toString() {

return (digits(mostSigBits >> 32, 8) + "-" +

digits(mostSigBits >> 16, 4) + "-" +

digits(mostSigBits, 4) + "-" +

digits(leastSigBits >> 48, 4) + "-" +

digits(leastSigBits, 12));

}

/** Returns val represented by the specified number of hex digits. */

private static String digits(long val, int digits) {

long hi = 1L << (digits * 4);

return Long.toHexString(hi | (val & (hi - 1))).substring(1);

}

源码里写的很清楚 是它自己干的,所以完全可以自己实现把“-”去掉(最终代码在后面)

2.21-22位的uuid

去掉“-”之后变成了9b8a013583ba42cba75a9f3d6471eb7a,是一个16进制的字符串,但还是太长

/*

* The most significant 64 bits of this UUID.

*

* @serial

*/

private final long mostSigBits;

/*

* The least significant 64 bits of this UUID.

*

* @serial

*/

private final long leastSigBits;

源码中的UUID类中的这两个long型属性(mostSigBits是前半部分,leastSigBits是后半部分),其实就代表了uuid,具体的字符串编码都是通过这两个long拼接起来的(不得不说,想法很鸡贼,正常看到的就是这两个的16进制字符串)。

有人说,那直接把“-”去掉使用base64转化成64进制的字符串不就短了很多了?是这样的,不过我们可以仿写base64的实现写个简单的(主要base64最后是拿“+”和“/”凑的64个,“/”在http传输中容易被误解析)

最终的UUIDUtils代码:

import java.util.Date;

import java.util.UUID;

/**

* Created by Kowalski on 2017/5/11

* Updated by Kowalski on 2017/5/11

*/

public final class UUIDUtils {

/**

* 采用URL Base64字符,即把“+/”换成“-_”

*/

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

/**21-22位UUID*/

public static String generateMost22UUID() {

UUID uid = UUID.randomUUID();

long most = uid.getMostSignificantBits();

char[] buf = new char[22];

int charPos = 22;

int radix = 1 << 6;

long mask = radix - 1;

do {

charPos--;

buf[charPos] = digits[(int)(most & mask)];

most >>>= 6;

} while (most != 0);

long least = uid.getLeastSignificantBits();

do {

charPos--;

buf[charPos] = digits[(int)(least & mask)];

least >>>= 6;

} while (least != 0);

return new String(buf, charPos, 22-charPos);

}

/**无 - UUID*/

public static String generateUUID() {

UUID uuid = UUID.randomUUID();

long most = uuid.getMostSignificantBits();

long least = uuid.getLeastSignificantBits();

return (digits(most >> 32, 8) +

digits(most >> 16, 4) +

digits(most, 4) +

digits(least >> 48, 4) +

digits(least, 12));

}

private static String digits(long val, int digits) {

long hi = 1L << (digits << 2);

return Long.toHexString(hi | (val & (hi - 1)));

}

/**22位UUID*/

public static String generateUUID22() {

UUID uuid = UUID.randomUUID();

long msb = uuid.getMostSignificantBits();

long lsb = uuid.getLeastSignificantBits();

char[] out = new char[24];

int tmp = 0, idx = 0;

// 循环写法

int bit = 0, bt1 = 8, bt2 = 8;

int mask = 0x00, offsetm = 0, offsetl = 0;

for(; bit < 16; bit += 3, idx += 4) {

offsetm = 64 - ((bit + 3) << 3);

offsetl = 0;

tmp = 0;

if(bt1 > 3) {

mask = (1 << 8 * 3) - 1;

} else if(bt1 >= 0) {

mask = (1 << 8 * bt1) - 1;

bt2 -= 3 - bt1;

} else {

mask = (1 << 8 * ((bt2 > 3) ? 3 : bt2)) - 1;

bt2 -= 3;

}

if(bt1 > 0) {

bt1 -= 3;

tmp = (int) ((offsetm < 0) ? msb : (msb >>> offsetm) & mask);

if(bt1 < 0) {

tmp <<= Math.abs(offsetm);

mask = (1 << 8 * Math.abs(bt1)) - 1;

}

}

if(offsetm < 0) {

offsetl = 64 + offsetm;

tmp |= ((offsetl < 0) ? lsb : (lsb >>> offsetl)) & mask;

}

if(bit == 15) {

out[idx + 3] = digits[64];

out[idx + 2] = digits[64];

tmp <<= 4;

} else {

out[idx + 3] = digits[tmp & 0x3f];

tmp >>= 6;

out[idx + 2] = digits[tmp & 0x3f];

tmp >>= 6;

}

out[idx + 1] = digits[tmp & 0x3f];

tmp >>= 6;

out[idx] = digits[tmp & 0x3f];

}

return new String(out, 0, 22);

}

public static void main(String... args) {

Date d5 = new Date();

for(int i = 0; i < 10000000; i++) {

generateUUID22();

}

Date d6 = new Date();

System.out.print(d6.getTime() - d5.getTime());

System.out.println("\n");

Date d1 = new Date();

for(int i = 0; i < 10000000; i++) {

generateMost22UUID();

}

Date d2 = new Date();

System.out.print(d2.getTime() - d1.getTime());

System.out.println("\n");

}

}

这种实现方式比用replace后再用base64转换速度要更快(接近一倍),这里都是为了保证uuid的精度实现的,对uuid精度要求较低的也可以使用其他位数更少的uuid变体,有更好方案的小伙伴来交流~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值