通常我们生成唯一序列号的时候喜欢把时间作为序列号的其中,但时间序列号的长度为15,加上其他诸如userid,商户merchantid等长度达到50~60位,这样导致我们的序列号就非常长导致。
1,存放时占用空间大,
2,查询时效率慢
我们是不是可以把时间序列号变短呢?
我们知道:
根据ascII编码表:
小写字符a(97) 使用不同存储时的编码长度
二进制:01100001
八进制:141
十进制:97
十六进制:61
可以看出,随着进制的增高,字符的长度也会越来越短,如果我们拿我们常用的0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ这个62个字符作为编码,那么62进制就可以表示了。
再进行编码前,我搜了一下git,上面已经有代码实现了(base62),我就不再实现一遍了,代码如下:
1.编码,将long型转换为62进制字符串
/**
* Encodes a decimal value to a Base62 <code>String</code>.
*
* @param b10
* the decimal value to encode, must be nonnegative.
* @return the number encoded as a Base62 <code>String</code>.
*/
public String encodeBase10(long b10) {
if (b10 < 0) {
throw new IllegalArgumentException("b10 must be nonnegative");
}
String ret = "";
while (b10 > 0) {
ret = characters.charAt((int) (b10 % 62)) + ret;
b10 /= 62;
}
return ret;
}
2.解码,逆过程
/**
* Decodes a Base62 <code>String</code> returning a <code>long</code>.
*
* @param b62
* the Base62 <code>String</code> to decode.
* @return the decoded number as a <code>long</code>.
* @throws IllegalArgumentException
* if the given <code>String</code> contains characters not
* specified in the constructor.
*/
public long decodeBase62(String b62) {
for (char character : b62.toCharArray()) {
if (!characters.contains(String.valueOf(character))) {
throw new IllegalArgumentException("Invalid character(s) in string: " + character);
}
}
long ret = 0;
b62 = new StringBuffer(b62).reverse().toString();
long count = 1;
for (char character : b62.toCharArray()) {
ret += characters.indexOf(character) * count;
count *= 62;
}
return ret;
}
测试用例(以15位的时间戳为例):
public static void main(String[] args) {
Base62 encoder=new Base62();
Long time=System.nanoTime();
String timeStr=encoder.encodeBase10(time);
System.out.println(timeStr);
System.out.println(time);
System.out.println(encoder.decodeBase62(timeStr));
}
console输出结果如下:
2OdCqJOH8
613534552694770
613534552694770
长度由15位变为9位,减少了40%的长度,当前查询效率也得到相应的提升了。
是不是蛮有趣的?