Java 字符串相似度计算,余弦算法
本文是计算两个字符串的相似度
具体步骤为
1、求出两个字符串的并集
2、计算两个字符串的词频
3、通过公式算出余弦值:夹角越小,相似度越大,越接近1,相似度越大
如:以下的其实是很接近的,那具体怎么算
String a1 = "今天天气真好";
String a2 = "今天天气不错";
1、算并集
{0=今, 1=天, 2=气, 3=真, 4=好, 5=不, 6=错}
2、算每个的词频
a1 = {0=1, 1=2, 2=1, 3=1, 4=1, 5=0, 6=0}
a2 = {0=1, 1=2, 2=1, 3=0, 4=0, 5=1, 6=1}
3、公式套用
(1*1 + 2*2+1*1+1*0+1*0+0*1+0*1)/ { [平方根号(1*1 + 2*2 + 1*1 + 1*1 + 1*1 + 0*0 + 0*0)] * [ 平方根号(1*1 + 2*2 + 1*1 + 0*0 + 0*0 + 1*1 + 1*1)] }
import java.util.HashMap;
import java.util.Map;
public class Cosine {
public static void main(String[] args) {
//String str = "国药准字H20090101";
String a1 = "今天天气真好";
String a2 = "今天天气不错";
long start=System.currentTimeMillis();
double jgz = getVector(a1, a2);
System.out.println("用时:"+(System.currentTimeMillis()-start));
System.out.println(jgz);
}
public static double getVector(String par,String bar){
Map<Integer, String> map = new HashMap<Integer, String>();
Map<Integer, String> map2 = new HashMap<Integer, String>();
Map<Integer, String> pmap = new HashMap<Integer, String>();
Map<Integer, String> bmap = new HashMap<Integer, String>();
// 词频存储的map
Map<Integer, Integer> pmapcp = new HashMap<Integer, Integer>();
Map<Integer, Integer> bmapcp = new HashMap<Integer, Integer>();
// 结果值
double jgz = -1;
par = qbdfh(par);
bar = qbdfh(bar);
if(isNull(par) || isNull(bar)) {
return -1;
}
String chb = par+bar; // 初合并
map = strChargeMap(chb); // 字符串放到map中
map2 = mapQC(map); // 合并为map,去重
//计算词频
pmap = strChargeMap(par);
bmap = strChargeMap(bar);
// 得到词频
pmapcp = getcipin(map2, pmap);
bmapcp = getcipin(map2, bmap);
// 计算夹角
jgz = getjgz(map2, pmapcp, bmapcp);
return jgz;
}
/**
* 计算余弦值
* @param map2 并集
* @param pmapcp p词频
* @param bmapcp b词频
* @return
*/
public static double getjgz(Map<Integer, String> map2, Map<Integer, Integer> pmapcp, Map<Integer, Integer> bmapcp) {
//计算的三个变量
double zx = 0; //分子
double ax = 0; //分母1
double bx = 0; //分母2
// 临时变量
double ap = 0;
double bp = 0;
// 结果值
double jgz = -1;
if(isNull(map2) || isNull2(pmapcp) || isNull2(bmapcp)) return -1;
for (int i = 0; i < map2.size(); i++) {
Integer a = pmapcp.get(i);
Integer b = bmapcp.get(i);
zx = zx + a*b;
ap = ap+a*a;
bp = bp+b*b;
}
ax = Math.pow(ap, 1.0/2);
bx = Math.pow(bp, 1.0/2);
if (zx == 0) return -1;
jgz = zx/(ax*bx);
return jgz;
}
/**
* 字符串词频计算
* @param map2 并集
* @param strmap 字符串map
* @return
*/
public static Map<Integer, Integer> getcipin(Map<Integer, String> map2, Map<Integer, String> strmap){
Map<Integer, Integer> cipin = new HashMap<Integer, Integer>();
if(isNull(map2) || isNull(strmap)) return null;
// 初始化词频
for (int i = 0; i < map2.size(); i++) {
cipin.put(i, 0);
}
// 词频赋值
for (int i = 0; i < map2.size(); i++) {
String map2value = map2.get(i);
for (int j = 0; j < strmap.size(); j++) {
String pmapvalue = strmap.get(j);
if(map2value.equals(pmapvalue)) {
cipin.put(i, cipin.get(i)+1);
}
}
}
return cipin;
}
/**
* map 去重
* @param map
* @return
*/
public static Map<Integer, String> mapQC(Map<Integer, String> map){
Map<Integer, String> map2 = new HashMap<Integer, String>();
int k = -1;
if(isNull(map)) return null;
for (int j = 0; j < map.size(); j++) {
if (!map2.containsValue(map.get(j))) {
k = k+1;
map2.put(k,map.get(j));
}
}
return map2;
}
/**
* 将字符串放到map中
* @param str
* @return
*/
public static Map<Integer, String> strChargeMap(String str){
Map<Integer, String> map = new HashMap<Integer, String>();
if(isNull(str)) return null;
for(int i=0;i<str.length();i++){
map.put(i, String.valueOf(str.charAt(i)));
}
return map;
}
public static boolean isNull2(Map<Integer, Integer> map) {
if(map == null || map.size() == 0) return true;
return false;
}
public static boolean isNull(Map<Integer, String> map) {
if(map == null || map.size() == 0) return true;
return false;
}
public static boolean isNull(String str) {
if(str == null || "".equals(str) || str.length() == 0) return true;
return false;
}
/**
* 去标点符号
* @param str
* @return
*/
public static String qbdfh(String str) {
if ("".equals(str) || str.length() == 0 || str == null) return "";
return str = str.replaceAll( "[\\pP+~$`^=|<>~`$^+=|<>¥×]" , "");
}
}
运行结果
用时:10
0.7499999999999999