11.23 序列號生成的另一種玩法--62進制如何玩?

通常我們生成唯一序列號的時候喜歡把時間作為序列號的其中,但時間序列號的長度為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;
}

測試用例:

 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%的長度,當前查詢效率也得到相應的提升了。

是不是蠻有趣的?


分享到:


相關文章: