在使用到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变体,有更好方案的小伙伴来交流~

UUID不失精度,长度改进的更多相关文章

  1. 【转】JAVA程序中Float和Double精度丢失问题

    原文网址:http://blog.sina.com.cn/s/blog_827d041701017ctm.html 问题提出:12.0f-11.9f=0.10000038,"减不尽" ...

  2. Java double和 float丢失精度问题

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt357 由于对float或double 的使用不当,可能会出现精度丢失的问题. ...

  3. java float double精度为什么会丢失?浅谈java的浮点数精度问题 【转】

    由于对float或double 的使用不当,可能会出现精度丢失的问题.问题大概情况可以通过如下代码理解: public class FloatDoubleTest { public static vo ...

  4. 分布式UUID的生成

    背景 最近有个项目:涉及到分布式计算,tps相对较高,流程之间是异步调用,流程间相互依赖的对象(涉及记录外键)需要持久化.这就衍生出了需要在JVM中快速生成分布式UUID的问题 方案 1.通过JDK标 ...

  5. float,double等精度丢失问题 float,double内存表示

    问题提出:12.0f-11.9f=0.10000038,"减不尽"为什么? 来自MSDN的解释: http://msdn.microsoft.com/zh-cn/c151dt3s. ...

  6. %.*lf控制输出长度

    #include<stdio.h> int main(){    int a,b,c;    while(scanf("%d%d%d",&a,&b,&a ...

  7. MySQL内置函数uuid和uuid_short

    MySQL的uuid这个函数.简要介绍一下. 用法 简单看到,这个值,每次执行都是不同的. 生成规则 第1 2 3 段是与时间有关的. time_low.time_mid.time_high_and_ ...

  8. JavaWeb网上图书商城完整项目-CommonUtils(1生成uuid,2Map转换成JavaBean)

    java工程中添加上面的jar包 CommonUtils类就两个方法: l  String uuid():生成长度32的随机字符,通常用来做实体类的ID.底层使用了UUID类完成: l  T toBe ...

  9. C++基础_总结

    (1)多态性都有哪些?(静态和动态,然后分别叙述了一下虚函数和函数重载) 多态分为两种:静态和动态.静态主要包括函数重载和模板:动态主要是依靠虚函数实现的. 静态联编:重载函数不加virtual关键字 ...

随机推荐

  1. js无缝滚动原理及详解[转自刹那芳华]

    刚刚接触JS,网上找了一些关于无缝滚动的教程,但都大同小异,对我这种新手来说也只是会用,不知道什么意思,想要自己写个更是一头雾水.于是找了一些资料,详细说明一下JS无缝滚动的原理,相信看过这篇文章之后 ...

  2. UML学习之初步总结

    UML(Unified Modeling Language)即统一建模语言,是一种开放的方法,用于说明.可视化.构建和编写一个正在开发的.面向对象的.软件密集系统的制品的开放方法.UML展现了一系列最 ...

  3. 如何使用 PyCharm 将代码上传到远程服务器上(详细图解)

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 一丶测试说明 1.通过Windows电脑上的PyCharm,将代码上传到虚拟机Ubuntu系统中 需要在虚拟机中安装Ubuntu的 ...

  4. [Android5.1]ActivityManagerService启动过程分析

    ActivityManagerService(简称AMS)是Android系统的关键服务之中的一个.它的主要作用例如以下: 管理系统中全部应用进程的整个生命周期 管理应用进程中的Activity.Se ...

  5. 自旋锁spinlock解析

    1 基础概念 自旋锁与相互排斥锁有点类似,仅仅是自旋锁不会引起调用者睡眠.假设自旋锁已经被别的运行单元保持.调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁."自旋"一词就 ...

  6. iOS之StatusBar详解

    随便打开手机上的主流APP,我们不难发现它们的状态栏都是跟导航栏保持一致的背景颜色,如下图的微信和instagram: WECHAT.PNG INS.PNG 那么今天我们就来说一下StatusBar这 ...

  7. 关于stm32加不进.h文件的问题

    把路径也设置好了,但是.h文件加入不进去, 编译的时候.h文件也出来了 那是因为.h或对应的.c文件中存在错误,改掉错误就能成功,有时候keil不会报错,可能是因为定义变量没有定义好 如果显示某个变量 ...

  8. 每日技术总结:Better-scroll应用于弹出层内容滚动

    一.Better-scroll在项目中的应用 Better-scroll这款滚动插件还是很好用的,通常不会有什么问题.但偶尔总会出点意外.今天再次使用better-scroll,记录一下这次顺利的过程 ...

  9. Understanding Cubert Concepts(一)Partitioned Blocks

    Understanding Cubert Concepts(一)Partitioned Blocks Cubert Concepts 对于Cubert,我们要理解其核心的一些概念,比方BLOCK.这些 ...

  10. go 保留小数若干位数

    感谢 https://blog.csdn.net/sjy8207380/article/details/79013827 解决的方法 · 利用取近似值的方法解决这个问题. (1)利用fmt.Sprin ...