本文介绍StringUtils的剩下的两个方法
1.计算两个字符串相似度
1.1实现简单介绍
实现原理可参考计算字符串相似度算法——Levenshtein
这里的算法区别在于:存差异值的数组由上文中的二维数组,变成这个实现的两个一维数组,并通过不断的交换数值来实现。
1.2源码理解
//计算两个字符串的差异值
public static int getLevenshteinDistance(CharSequence s, CharSequence t) {
if (s == null || t == null) {
//容错,抛出的这个异常是表明在传参的时候,传递了一个不合法或不正确的参数。 好像都这样用,illegal:非法。Argument:参数,证据。
throw new IllegalArgumentException("Strings must not be null");
}
//计算传入的两个字符串长度
int n = s.length();
int m = t.length();
//容错,直接返回结果。这个处理不错
if (n == 0) {
return m;
} else if (m == 0) {
return n;
}
//这一步是根据字符串长短处理,处理后t为长字符串,s为短字符串,方便后面处理
if (n > m) {
CharSequence tmp = s;
s = t;
t = tmp;
n = m;
m = t.length();
}
//开辟一个字符数组,这个n是短字符串的长度
int p[] = new int[n + 1];
int d[] = new int[n + 1];
//用于交换p和d的数组
int _d[];
int i;
int j;
char t_j;
int cost;
//赋初值
for (i = 0; i <= n; i++) {
p[i] = i;
}
for (j = 1; j <= m; j++) {
//t是字符串长的那个字符
t_j = t.charAt(j - 1);
d[0] = j;
for (i = 1; i <= n; i++) {
//计算两个字符是否一样,一样返回0。
cost = s.charAt(i - 1) == t_j ? 0 : 1;
//可以将d的字符数组全部赋值。
d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
}
//交换p和d
_d = p;
p = d;
d = _d;
}
//最后的一个值即为差异值
return p[n];
}
差异值算出来后,除以字符串长度就能算出相似度。
2.去掉字符串中的口音(就是将Ë 转换成 E)
public static String stripAccents(String input) {}
在这个方法的注释里面,写到java1.6 用到的是java.text.Normalizer,java1.3-1.5用的是sun.text.Normalizer。
同时建议让我们去参考Lucene2.9 的ASCIIFoldingFilter。
2.1带口音的字符从哪里来
首先ASCII码是八位,但是只用到0-127,最高位是用于校验,128-255被用到这样‘Î’,’ Ë‘ 的字符,未收录ASCII中。所以这个方法是将这些带有口音的字符变成标准的(a-z)|(A-Z)。
举例:前面是ascII编码,后面是字符
226:â
227:ã
228:ä
229:å
230:æ
231:ç
232:è
233:é
234:ê
2.2源码理解
这个源码对我来说不容易看,对字符编码之间的转换不理解,看源码会有点吃力,费很多时间,所以就不看了,实现的话,大概就是先把需要转换的部分转换成标准编码,再删除多余的字符。java的字符编码是UTF-8,所以应该变为UTF-8。
3.结束
StringUtils看完了,这两个方法查了不少东西才看下来,同时也学了很多。