我正在比较两个字符串列表以找到可能的匹配项。例如:
public class Tester {
public static void main(String[] args) {
List<String> test = new ArrayList<String>();
List<String> test2 = new ArrayList<String>();
test.add("3H0875AAAA0012");
test.add("3H0875AABB0018");
test.add("3H0875AAAC0010");
test2.add("3H0875AA");
for(String s2: test2){
for (String s: test){
if (s.matches(".*" + s2 + ".*")){
System.out.println("Match");
}
}
}
}
}
基本上对于test2
中的每个字符串,我想查看test
中是否有完全或部分包含test2
的字符串。上述代码的输出应为:
Match
Match
Match
然而,在我的实际情况中,我在测试中有大约225K个字符串,在test2中有大约5K个字符串。这个比较需要太长的过程,并想看看是否有可能优化比较。分析test2中的前1.5K项需要大约10分钟。因此完成比较至少需要30到40分钟。
提前致谢
答案 0 :(得分:3)
我认为你不应该使用正则表达式:我相信调查String#contains
(这里是link to its javadoc entry)会给你更好的结果,在表现方面;)
例如,您的代码可能是:
for(final String s2: test2){
for (final String s: test){
if(s.contains(s2)) {
System.out.println("Match");
}
}
}
答案 1 :(得分:1)
应该禁止像String.matches(String)
这样的恕我直言方法。也许你需要一个正则表达式匹配,也许不是,但这里发生的是,你的字符串被一次又一次编译成一个正则表达式。
请自己帮个忙,然后通过Pattern.compile
将所有内容转换为正则表达式并重复使用。
看着你的".*" + s2 + ".*"
,我敢打赌你根本不需要正则表达式。只需使用String.contains
并享受速度。
答案 2 :(得分:1)
而不是
s.matches(".*" + s2 + ".*")
你可以使用
s.contains(s2)
或
s.indexOf(s2) > -1
我测试了两者,每张都比matches
快了35倍。
答案 3 :(得分:0)
在这种情况下,您绝对应该创建一个Matcher
对象,并在每次循环迭代中使用该单个对象。您当前正在每次循环迭代中创建一个新的匹配器(并编译一个新的Pattern
)。
在代码的顶部,执行以下操作:
//"": Unused to-search string, so the matcher object can be reused
Matcher mtchr = Pattern.compile(".*" + s2 + ".*").matcher("");
然后在循环中,执行以下操作:
if(mtchr.reset(s).matches()) {
...
但我同意@maaartinus,并说,根据您的要求,您根本不需要正则表达式,而是可以使用indexOf(s)
,甚至更好,contains(s)
,因为你似乎不需要得到的索引。
无论如何,重用匹配器的这个概念是非常宝贵的。