我有以下功能。
private boolean codeContains(String name, String code) {
if (name == null || code == null) {
return false;
}
Pattern pattern = Pattern.compile("\\b" + Pattern.quote(name) + "\\b");
Matcher matcher = pattern.matcher(code);
return matcher.find();
}
在我的代码中被称为数千次,并且是我的程序花费最多时间的函数。有没有办法让这个函数更快,或者它已经快到可以了?
答案 0 :(得分:4)
如果您不需要检查字边界,可以这样做:
private boolean codeContains(String name, String code) {
return name != null && code != null && code.indexOf(name)>=0;
}
如果你需要检查单词边界,但是,正如我想的那样,你有一个很大的code
经常搜索,你可以“编译”code
一次
code
字符串
当然,如果你有多个代码,很容易将它们存储在适合你程序的结构中,例如在具有文件名密钥的地图中。
答案 1 :(得分:1)
“普通”字符串操作(几乎)总是比正则表达式更快,特别是当你无法预编译模式时。
这样的事情会快得多(name
和code
字符串足够大),假设Character.isLetterOrDigit(...)
符合您的需求:
private boolean codeContains(String name, String code) {
if (name == null || code == null || code.length() < name.length()) {
return false;
}
if (code.equals(name)) {
return true;
}
int index = code.indexOf(name);
int nameLength = name.length();
if (index < 0) {
return false;
}
if (index == 0) {
// found at the start
char after = code.charAt(index + nameLength);
return !Character.isLetterOrDigit(after);
}
else if (index + nameLength == code.length()) {
// found at the end
char before = code.charAt(index - 1);
return !Character.isLetterOrDigit(before);
}
else {
// somewhere inside
char before = code.charAt(index - 1);
char after = code.charAt(index + nameLength);
return !Character.isLetterOrDigit(after) && !Character.isLetterOrDigit(before);
}
}
小测试成功了:
@Test
public void testCodeContainsFaster() {
final String code = "FOO some MU code BAR";
org.junit.Assert.assertTrue(codeContains("FOO", code));
org.junit.Assert.assertTrue(codeContains("MU", code));
org.junit.Assert.assertTrue(codeContains("BAR", code));
org.junit.Assert.assertTrue(codeContains(code, code));
org.junit.Assert.assertFalse(codeContains("FO", code));
org.junit.Assert.assertFalse(codeContains("BA", code));
org.junit.Assert.assertFalse(codeContains(code + "!", code));
}
答案 2 :(得分:0)
这段代码好像是这样做的:
private boolean codeContains(String name, String code) {
if (name == null || code == null || name.length() == 0 || code.length() == 0) {
return false;
}
int nameLength = name.length();
int lastIndex = code.length() - nameLength;
if (lastIndex < 0) {
return false;
}
for (int curr = 0; curr < lastIndex; ) {
int index = code.indexOf(name, curr);
int indexEnd = index + nameLength;
if (index < 0 || lastIndex < index) {
break;
}
boolean leftOk = index == curr ||
index > curr && !Character.isAlphabetic(code.charAt(index - 1));
boolean rightOk = index == lastIndex ||
index < lastIndex && !Character.isAlphabetic(code.charAt(indexEnd));
if (leftOk && rightOk) {
return true;
}
curr += indexEnd;
}
return false;
}
接受的答案是破坏性的,因为他是第一个指出我正确方向的人,但是Bart Kiers的出色回答,+ 1!