查找字符串集合中以某些字符开头的字符串的最快方法

时间:2013-09-02 01:58:59

标签: java collections partial string-matching

我有很多字符串。我希望能够找到以“Foo”开头的字符串或以“Bar”结尾的字符串。什么是最好的收集类型,以获得最快的结果? (我正在使用Java)

我知道HashSet对于完整的匹配非常快,但不是我认为的部分匹配?那么,我可以使用什么而不是仅仅循环List?我应该查看LinkedList或类似的类型吗?是否有针对此类查询优化的任何集合类型?

3 个答案:

答案 0 :(得分:3)

此问题的最佳收藏类型为SortedSet。实际上你需要其中两个:

  1. 正常的单词。
  2. 字符倒置的字词。
  3. 创建这些SortedSet后,您可以使用方法subSet找到您要查找的内容。例如:

    1. "Foo"开头的字词:

       forwardSortedSet.subSet("Foo","Fop");
      
    2. "Bar"结尾的字词:

       backwardSortedSet.subSet("raB","raC");
      
    3. 我们在最后一个搜索字符中“添加”1的原因是为了获得整个范围。 “结束”一词从subSet中排除,因此没有问题。

      编辑:在标准Java库中实现SortedSet的两个具体类中,使用TreeSet。另一个(ConcurrentSkipListSet)面向并发程序,因此没有针对这种情况进行优化。

答案 1 :(得分:3)

已经有一段时间了,但我现在需要实现它并进行一些测试。

我已经有HashSet<String>作为来源,所以所有其他数据结构的生成都包含在搜索时间中。使用100个不同的源,每次需要重新生成数据结构。我每次只需要匹配几个单独的字符串。这些测试在Android上运行。

方法:

  1. 通过HashSet进行简单循环,然后致电endsWith() 每个字符串

  2. 通过HashSet进行简单循环并执行预编译     Pattern匹配(正则表达式)每个字符串。

  3. HashSet转换为String\n加入的单SortedTree     整个String上的单一匹配。

  4. 使用反向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) 匹配。

  5. 结果:

    SortedSet

    结论:

    SortedTree / Strings搜索速度非常快。比循环遍历所有String要快得多。但是,创建结构需要花费大量时间。正则表达式要慢得多,但在数百Strings中生成一个大的SortedTree更多是Android / Java的瓶颈。

    如果只需要制作几个匹配项,那么最好循环收集。如果您有更多匹配项,那么使用{{1}}可能非常有用!

答案 2 :(得分:2)

如果单词列表稳定(添加或删除的单词不多),那么非常好的第二种选择是创建2个列表:

  1. 一个正常顺序的单词。
  2. 第二个,每个单词中的字符都相反。
  3. 出于速度目的,请将它们设为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++;
        }