java判断两个字符串相似的方法
判断两个字符串相似的方法
- 在Java中,我们经常需要判断两个字符串是否相似,以便进行文本匹配、数据清洗、搜索等操作。本文将介绍几种常见的方法用于判断两个字符串的相似度,并提供相应的Java代码示例。
比较字符串的相似度
- 在实际应用中,判断两个字符串的相似度常常是通过计算它们的相似度系数来实现的。常见的相似度系数包括编辑距离、余弦相似度、Jaccard系数等。
编辑距离
-
编辑距离,也称为Levenshtein距离,是一种用于字符串相似度比较的常见方法。它表示将一个字符串转换为另一个字符串所需的最少操作数。
-
public int calculateEditDistance(String s1, String s2) { int m = s1.length(); int n = s2.length(); int[][] dp = new int[m+1][n+1]; for (int i = 0; i <= m; i++) { dp[i][0] = i; } for (int j = 0; j <= n; j++) { dp[0][j] = j; } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (s1.charAt(i-1) == s2.charAt(j-1)) { dp[i][j] = dp[i-1][j-1]; } else { dp[i][j] = Math.min(dp[i-1][j-1] + 1, Math.min(dp[i][j-1] + 1, dp[i-1][j] + 1)); } } } return dp[m][n]; }
-
以上代码演示了如何使用动态规划算法计算两个字符串之间的编辑距离。其中 s1 和 s2 分别是要比较的两个字符串,函数返回它们的编辑距离。
余弦相似度
-
余弦相似度是一种常用的度量两个向量之间相似度的方法,可以用于度量两个字符串之间的相似度。
-
public double calculateCosineSimilarity(String s1, String s2) { Map<Character, Integer> v1 = generateVector(s1); Map<Character, Integer> v2 = generateVector(s2); double dotProduct = 0.0; double norm1 = 0.0; double norm2 = 0.0; for (Character key : v1.keySet()) { if (v2.containsKey(key)) { dotProduct += v1.get(key) * v2.get(key); } norm1 += Math.pow(v1.get(key), 2); } for (Character key : v2.keySet()) { norm2 += Math.pow(v2.get(key), 2); } double similarity = dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2)); return similarity; } private Map<Character, Integer> generateVector(String s) { Map<Character, Integer> vector = new HashMap<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (vector.containsKey(c)) { vector.put(c, vector.get(c) + 1); } else { vector.put(c, 1); } } return vector; }
-
以上代码演示了如何使用余弦相似度计算两个字符串之间的相似度。函数 calculateCosineSimilarity 接受两个字符串 s1 和 s2,返回它们的余弦相似度。
Jaccard系数
-
Jaccard系数是一种用于计算两个集合之间相似度的方法,也可以用于度量两个字符串之间的相似度。
-
import java.util.HashSet; import java.util.Set; import java.util.HashMap; import java.util.Map; public class Main { public static double calculateJaccardSimilarity(String str1, String str2) { // 将字符串转换为字符集合 Set<Character> set1 = new HashSet<>(); for (char c : str1.toCharArray()) { set1.add(c); } Set<Character> set2 = new HashSet<>(); for (char c : str2.toCharArray()) { set2.add(c); } // 计算交集和并集 Set<Character> intersection = new HashSet<>(set1); intersection.retainAll(set2); // 交集 Set<Character> union = new HashSet<>(set1); union.addAll(set2); // 并集 // 如果并集为空,则相似度为0(避免除以0的情况) if (union.isEmpty()) { return 0.0; } // 计算Jaccard相似度 double jaccardSimilarity = (double) intersection.size() / union.size(); return jaccardSimilarity; } public static void main(String[] args) { String str1 = "这两天,河北廊坊市人民医院退还核酸检测费的消息引发热议。奔流新闻记者从廊坊市人民医院财务科证实,“从5月20日开始对收到短信的市民退费,多数成年人已经完成退费,今天开始对青少年儿童退费。”"; String str2 = "5月20日,一些市民收到廊坊市人民医院发来的短信:按上级要求退还2020年至2021年核酸检测费。请持身份证于5月20日-6月20日工作日时间到市医院财务部退费。"; double similarity = calculateJaccardSimilarity(str1, str2); System.out.println("Jaccard Similarity: " + similarity); } }