我有很多字符串。我希望能够找到以“Foo”开头的字符串或以“Bar”结尾的字符串。什么是最好的收集类型,以获得最快的结果? (我正在使用Java)
我知道HashSet对于完整的匹配非常快,但不是我认为的部分匹配?那么,我可以使用什么而不是仅仅循环List?我应该查看LinkedList或类似的类型吗?是否有针对此类查询优化的任何集合类型?
答案 0 :(得分:3)
此问题的最佳收藏类型为SortedSet
。实际上你需要其中两个:
创建这些SortedSet
后,您可以使用方法subSet
找到您要查找的内容。例如:
以"Foo"
开头的字词:
forwardSortedSet.subSet("Foo","Fop");
以"Bar"
结尾的字词:
backwardSortedSet.subSet("raB","raC");
我们在最后一个搜索字符中“添加”1的原因是为了获得整个范围。 “结束”一词从subSet
中排除,因此没有问题。
编辑:在标准Java库中实现SortedSet
的两个具体类中,使用TreeSet
。另一个(ConcurrentSkipListSet
)面向并发程序,因此没有针对这种情况进行优化。
答案 1 :(得分:3)
已经有一段时间了,但我现在需要实现它并进行一些测试。
我已经有HashSet<String>
作为来源,所以所有其他数据结构的生成都包含在搜索时间中。使用100个不同的源,每次需要重新生成数据结构。我每次只需要匹配几个单独的字符串。这些测试在Android上运行。
方法:
通过HashSet
进行简单循环,然后致电endsWith()
每个字符串
通过HashSet
进行简单循环并执行预编译
Pattern
匹配(正则表达式)每个字符串。
将HashSet
转换为String
和\n
加入的单SortedTree
整个String上的单一匹配。
使用反向Strings
生成HashSet
subset()
。然后按照@Mario Rossi的解释与Duration for method 1: 173ms (data setup:0ms search:173ms)
Duration for method 2: 6909ms (data setup:0ms search:6909ms)
Duration for method 3: 3026ms (data setup:2377ms search:649ms)
Duration for method 4: 2111ms (data setup:2101ms search:10ms)
匹配。
结果:
SortedSet
结论:
SortedTree
/ Strings
搜索速度非常快。比循环遍历所有String
要快得多。但是,创建结构需要花费大量时间。正则表达式要慢得多,但在数百Strings
中生成一个大的SortedTree
更多是Android / Java的瓶颈。
如果只需要制作几个匹配项,那么最好循环收集。如果您有更多匹配项,那么使用{{1}}可能非常有用!
答案 2 :(得分:2)
如果单词列表稳定(添加或删除的单词不多),那么非常好的第二种选择是创建2个列表:
出于速度目的,请将它们设为ArrayList
。从不LinkedList
s或其他在随机访问中表现极差的变体(二进制搜索的核心;见下文)。
创建列表后,可以使用方法Collections.sort
对其进行排序(每次只有一次),然后使用Collections.binarySearch
进行搜索。例如:
Collections.sort(forwardList);
Collections.sort(backwardList);
然后搜索以“Foo”开头的单词:
int i= Collections.binarySearch(forwardList,"Foo") ;
while( i < forwardList.size() && forwardList.get(i).startsWith("Foo") ) {
// Process String forwardList.get(i)
i++;
}
以“Bar”结尾的单词:
int i= Collections.binarySearch(backwardList,"raB") ;
while( i < backwardList.size() && backwardList.get(i).startsWith("raB") ) {
// Process String backwardList.get(i)
i++;
}