下面是從網上找到了一些算法總結:
算法一:
最容易想到的算法可能是利用md5類的加密算法,然後針對加密後的字符串進行處理。
1)將長網址md5生成32位簽名串,分爲4段, 每段8個字節;2)對這四段循環處理, 取8個字節, 將他看成16進制串與0x3fffffff(30位1)與操作, 即超過30位的忽略處理;
3)這30位分成6段, 每5位的數字作爲字母表的索引取得特定字符, 依次進行獲得6位字符串;
4)總的md5串可以獲得4個6位串; 取裏面的任意一個就可作爲這個長url的短url地址。
算法二:
a-zA-Z0-9 這64位取6位組合,可產生500多億個組合數量。把數字和字符組合做一定的映射,就可以產生唯一的字符串,如第62個組合就是aaaaa9,第63個組合就是aaaaba,再利用洗牌算法,把原字符串打亂後保存,那麼對應位置的組合字符串就會是無序的組合。
把長網址存入數據庫,取返回的id,找出對應的字符串,例如返回ID爲1,那麼對應上面的字符串組合就是bbb,同理 ID爲2時,字符串組合爲bba,依次類推,直至到達64種組合後纔會出現重複的可能,所以如果用上面的62個字符,任意取6個字符組合成字符串的話,你的數據存量達到500多億後纔會出現重複的可能。
下面自己簡單模擬了一個返回8位隨即碼的短網址算法,算法實現基於算法一。
public class ShortUrlUtil {
static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f' };
public static String shortUrl(String url) throws Exception {
MessageDigest messagedigest = MessageDigest.getInstance("MD5");
messagedigest.update(url.getBytes());
String result = bufferToHex(messagedigest.digest());
String resUrl = new String("");
for (int i = 0; i < 8; i++) {
String tmpString = result.substring(i * 4, i * 4 + 4);
long hexLong = 0x3FFFFFFF & Long.parseLong(tmpString, 16);
resUrl += hexDigits[Integer.valueOf((hexLong % 16) + "")] + "";
}
return resUrl;
}
private static String bufferToHex(byte bytes[]) {
return bufferToHex(bytes, 0, bytes.length);
}
private static String bufferToHex(byte bytes[], int m, int n) {
StringBuffer stringbuffer = new StringBuffer(2 * n);
int k = m + n;
for (int l = m; l < k; l++) {
appendHexPair(bytes[l], stringbuffer);
}
return stringbuffer.toString();
}
private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
char c0 = hexDigits[(bt & 0xf0) >> 4];
char c1 = hexDigits[bt & 0xf];
stringbuffer.append(c0);
stringbuffer.append(c1);
}
public static void main(String[] args) {
String sLongUrl = "http://weibo.com/taobaotianshui?wvr=5&wvr=5&lf=reg";
String shortUrl;
try {
shortUrl = shortUrl(sLongUrl);
System.out.println(sLongUrl + " ===> " + shortUrl);
} catch (Exception e) {
e.printStackTrace();
}
}
}
當生成短網址鏈接之後,只需要在表中(數據庫或者類NoSql的K-V存儲)存儲原始鏈接與短鏈接的映射關係即可。