我有一个字符串数组(关键字),我需要检查一个更大的字符串中存在多少个字符串(从文件中读取的文本)。我需要检查不区分大小写。 在这一刻,我所做的就是:
private void findKeywords() {
String body = email.getMessage();
for (String word : keywords) {
if (body.toLowerCase().contains(word.toLowerCase())) {
//some actions }
if (email.getSubject().contains(word)) {
//some actions
}
}
}
从这里阅读问题,另一个解决方案出现了:
private void findKeywords() {
String body = email.getMessage();
for (String word : keywords) {
boolean body_match = Pattern.compile(Pattern.quote(word), Pattern.CASE_INSENSITIVE).matcher(body).find();
boolean subject_match = Pattern.compile(Pattern.quote(word), Pattern.CASE_INSENSITIVE).matcher(email.getSubject()).find();
if (body_match) {
rating++;
}
if (subject_match) {
rating++;
}
}
}
哪些解决方案效率更高?还有另一种方法可以做到这一点更好吗?任何可接受的解决方案都必须易于实现(与上述相同),最好没有外部库,因为在这种情况下这不是一个非常重要的问题。
答案 0 :(得分:2)
这两种解决方案对我来说都是可行的。我建议的一个改进是将函数移出循环。在您当前的代码中,您反复执行诸如toLowerCase()和Pattern.compile之类的操作,您只需执行一次。
显然,有更快的方法可以解决这个问题,但它们需要比这些5行更复杂的代码。
答案 1 :(得分:1)
更好:使用所有关键字构建单一模式。然后搜索该模式。假设您的关键字不包含元字符(模式中具有特殊含义的字符),请使用:
StringBuilder keywordRegex = new StringBuilder();
for (String w : keywords) {
keywordRegex.append("|"+w);
}
Pattern p = Pattern.compile(keywordRegex.substring(1));
Matcher m = new p.matcher(textToMatch);
while (m.find()) {
// match is at m.start(); word is m.group(0);
}
比迭代所有关键字更有效:模式编译(一次)将生成一个自动搜索,一次查找所有关键字。
答案 2 :(得分:0)
我认为你提到的显式正则表达式解决方案会更有效率,因为它没有toLowerCase操作,它会将输入字符串复制到内存中并使字符小写。
这两种解决方案都应该是实用的,你的问题主要是学术性的,但我认为正则表达式提供了更清晰的代码。
答案 3 :(得分:0)
如果您的电子邮件正文非常大,编写一个专门的不区分大小写的包含可能是合理的,因为您可以避免在大字符串上调用toUpperCase():
static bool containsIgnoreCase(String big, String small) {
if (small == null || big == null || small.length() > big.length()) {
return false;
}
String smallLC = small.toLowerCase();
String smallUC = small.toUpperCase();
for (int i = 0; i < big.length(); ++i) {
if (matchesAt(big, i, smallLC, smallUC)) {
return true;
}
}
return false;
}
private static bool matchesAt(String big, int index, String lc, String uc) {
if (index + lc.length() > big.length()) {
return false;
}
for (int i = 0; i < lc.length(); ++i) {
char c = big.charAt(i + index);
if ((c != lc.charAt(i)) && (c != uc.charAt(i))) {
return false;
}
}
return true;
}