一般咱们生成惟一序列号的时候喜欢把时间做为序列号的其中,但时间序列号的长度为15,加上其余诸如userid,商户merchantid等长度达到50~60位,这样致使咱们的序列号就很是长致使。git
1,存放时占用空间大,ide
2,查询时效率慢测试
咱们是否是能够把时间序列号变短呢?编码
咱们知道:code
根据ascII编码表:blog
小写字符a(97) 使用不一样存储时的编码长度ci
二进制:01100001字符串
八进制:141string
十进制:97it
十六进制: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%的长度,当前查询效率也获得相应的提高了。
是否是蛮有趣的?