短地址,就是把长的URL转成短URL, 目前谷歌/新浪/百度/腾讯等都免费提供API服务。因调用次数限制或提供出去的url域名不是想要的,因此考虑自己实现。
短址本质上是实现了一个映射函数 f: X -> Y 。而这个映射函数必须同时具有两个特点:
1. 如果 x1 != x2, 则 f (x1) != f(x2);
2. 对于每一个 y, 能够找到唯一的一个 x 使得 f(x) = y;
对于任何的线性函数,比如 f(x) = 2x,都满足这样的条件。
实现:
短址的长度可以是任意位数,如6,7,8等,而每一位可以由 [a - z, A - Z, 0 - 9, - _] 总共 64 个字母/数字/符号组成的,所以6位的话,总共会有 64^6 ~= 几百亿种组合,足够使用。在百度地图服务中,短址长度为5,如:http://j.map.baidu.com/fSask
本文的思路通过进制之间的转换。规则如下:
0 → a
1 → b
...
25 → z
...
52 → 0
61 → 9
62 → -
63 → _
假设我们用数据库来保存长地址和短地址的映射,那么,在表 ShortURL 中,我们会有三列:
id, integer, auto-increment //ID,自动增长
long, string, the long URL the user entered //长URL
short, string, the shortened URL (or just the six characters) //短URL
1. 记录写入表 ShortURL ,得到ID
2. 十进制的ID转换成64进制短串,如果约定6位短串的话,不够位数则在前面补0,例如ID=123123 对应的短串为 aaaEdZ
实现如下:
public static final String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
public static final int BASE = ALPHABET.length();
public static String encode(int num) {
StringBuilder str = new StringBuilder();
while (num > 0) {
str.insert(0, ALPHABET.charAt(num % BASE));
num = num / BASE;
}
int len = str.length();
for (int i = 1; i <= 6 - len; i++) {
str.insert(0, ALPHABET.charAt(0));
}
return str.toString();
}
1. 通过短地址得到ID
2. 通过ID查 ShortURL ,得到长地址
实现如下:
public static int decode(String str) {
int id = 0;
int size = str.length();
for (int i = 0; i < size; i++) {
int value = ALPHABET.indexOf(str.charAt(i));
id += (int) (value * Math.pow(BASE, size - i - 1));
}
return id;
}
实例源码:test2-shorturl