短網址(Short URL) ,顧名思義就是看起來很短的網址。自從twitter推出短網址服務以后,各大互聯網公司都推出了自己的短網址服務。短網址最大的優點就是短,字符少,便于發布、傳播、復制和存儲。
通過網上的搜索,感覺流傳了2種短網址算法,一種是基于MD5碼的,一種是基于自增序列的。
1、基于MD5碼 : 這種算法計算的短網址長度一般是5位或者6位,計算過程中可能出現碰撞(概率很小),可表達的url數量為62
的5次方或6次方。感覺google(http://goo.gl),微博用的是類似這種的算法(猜的),可能看起來比較美觀。
2、基于自增序列 : 這種算法實現比較簡單,碰撞的可能性為0,可表達的URL可達無窮大,長度從1開始。貌似百度的短網址服務( http://dwz.cn/ )是這種算法.
具體算法
1、MD5碼:假設url的長度為N
a.計算長地址的MD5碼,將32位的MD碼分成4段,每段8個字符
b.將a得到的8個字符串看成一個16進制的數,與N * 6個1表示的二進制數進行&操作
得到一個N * 6長的二進制數
c.將b得到的數分成N段,每段6位,然后將這N個6位數分別與61進行&操作,將得到的
數作為INDEX去字母表取相應的字母或數字,拼接就是一個長度為N的短網址。
1
2
3
4
5
|
static final char [] DIGITS = { '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' }; |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public String shorten(String longUrl, int urlLength) { if (urlLength < 0 || urlLength > 6 ) { throw new IllegalArgumentException( "the length of url must be between 0 and 6" ); } String md5Hex = DigestUtils.md5Hex(longUrl); // 6 digit binary can indicate 62 letter & number from 0-9a-zA-Z int binaryLength = urlLength * 6 ; long binaryLengthFixer = Long.valueOf(StringUtils.repeat( "1" , binaryLength), BINARY); for ( int i = 0 ; i < 4 ; i++) { String subString = StringUtils.substring(md5Hex, i * 8 , (i + 1 ) * 8 ); subString = Long.toBinaryString(Long.valueOf(subString, 16 ) & binaryLengthFixer); subString = StringUtils.leftPad(subString, binaryLength, "0" ); StringBuilder sbBuilder = new StringBuilder(); for ( int j = 0 ; j < urlLength; j++) { String subString2 = StringUtils.substring(subString, j * 6 , (j + 1 ) * 6 ); int charIndex = Integer.valueOf(subString2, BINARY) & NUMBER_61; sbBuilder.append(DIGITS[charIndex]); } String shortUrl = sbBuilder.toString(); if (lookupLong(shortUrl) != null ) { continue ; } else { return shortUrl; } } // if all 4 possibilities are already exists return null ; } |
2、自增序列:
a. 或者序列的自增值,將值用62進制表示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
private AtomicLong sequence = new AtomicLong( 0 ); @Override protected String shorten(String longUrl) { long myseq = sequence.incrementAndGet(); String shortUrl = to62RadixString(myseq); return shortUrl; } private String to62RadixString( long seq) { StringBuilder sBuilder = new StringBuilder(); while ( true ) { int remainder = ( int ) (seq % 62 ); sBuilder.append(DIGITS[remainder]); seq = seq / 62 ; if (seq == 0 ) { break ; } } return sBuilder.toString(); } |
MAVEN工程中的代碼用2個MAP來模擬存放長-短網址的互相映射,實際使用中可能是基于數據庫表配合索引或者一些分布式KV系統來實現。
希望本文所述對大家學習短網址服務有所幫助。