在JAVA中查找子字符串的最快方法

时间:2014-01-20 12:20:09

标签: java performance arraylist substring

假设我有名单。

ArrayList<String> nameslist = new ArrayList<String>();
nameslist.add("jon");
nameslist.add("david");
nameslist.add("davis");
nameslist.add("jonson");

此列表中包含数千个名单。知道这个列表包含以给定名称开头的名称的方法是什么。

String name = "jon"

结果应为2.

我试过将list的每个元素与substring函数进行比较(它可以工作但是)当列表很大时,它非常慢。

谢谢你的到来。

10 个答案:

答案 0 :(得分:7)

您可以使用TreeSet进行O(log n)访问,并编写如下内容:

TreeSet<String> set = new TreeSet<String>();
set.add("jon");
set.add("david");
set.add("davis");
set.add("jonson");
set.add("henry");

Set<String> subset = set.tailSet("jon");
int count = 0;
for (String s : subset) {
    if (s.startsWith("jon")) count++;
    else break;
}
System.out.println("count = " + count);

按预期打印2个。

或者,您可以使用Set<String> subset = set.subSet("jon", "joo");返回以"jon"开头的完整名称列表,但是您需要在jons之后提供第一个无效条目(在这种情况下:“joo” “)。

答案 1 :(得分:2)

看看Trie。它是一种旨在根据字前缀执行快速搜索的数据结构。您可能需要稍微操作它以获取子树中的叶子数,但无论如何您都不会遍历整个列表。

Example tree

答案 2 :(得分:1)

ArrayList(或线性数组)中搜索的复杂性为O(n),其中n是数组中元素的数量。

为获得最佳效果,您可以看到Trie

答案 3 :(得分:0)

对每个元素的ArrayList进行迭代,检查它是否以jon开头。时间复杂度为O(n)。

答案 4 :(得分:0)

您需要迭代每个名称并在其中找到名称。

String name = "jon";
int count=0;
for(String n:nameslist){
    if(n.contains(name){
        count++;
    }   
}

答案 5 :(得分:0)

“非常慢”究竟是什么意思?

实际上,唯一的方法是遍历列表并检查每个元素:

int count = 0;
for (String name : nameslist) {
    if (name.startsWith("jon")) {
        count++;
    }
}

System.out.println("Found: " + count);

答案 6 :(得分:0)

如果列表中的字符串不是太长,你可以使用这个作弊:在HashSet中存储所有前缀,你的复杂性将是~O(1):

// Preprocessing
List<String> list = Arrays.asList("hello", "world"); // Your list
Set<String> set = new HashSet<>()
for(String s: list) {
  for (int i = 1; i <= s.length; i++) {
    set.add(s.substring(0, i));
  }
}

// Now you want to test
assert true == set.contains("wor") 

如果不是,您可以使用任何全文搜索引擎,例如Apache Lucene

答案 7 :(得分:0)

我建议您创建一个Runnable来处理列表元素。然后创建一个具有固定池大小的ExecutorService,它同时处理元素。

粗略的例子:

ExecutorService executor = Executors.newFixedThreadPool(5);
for (String str : coll){
    Runnable r = new StringProcessor(str);
    executor.execute(r);
}

答案 8 :(得分:0)

我建议使用TreeSet。

以类似方式访问每个元素并增加计数。算术上你可以改善表现。

   int count = 0;
   iter = list.iterator(); 
   String name;
   while(iter.hasNext()) {
        name = iter.next();
        if (name.startsWith("jon")) {
            count++;
        }
        if(name.startsWith("k")) break;
    }

这个中断消除了对其余字符串比较的检查。

答案 9 :(得分:0)

您可以考虑Boyer–Moore string search algorithm。 复杂性O(n + m)最坏的情况。