2011-10-06 119 views
3

我有一个arraylist<string>的话。我使用Collections.sort(wordsList);Java:如何搜索字符串的一部分数组

我正在使用这个数组作为自动建议下拉框,以便当用户输入一个字母时,他们会得到一个类似于他们输入内容的建议列表。

我该如何去搜索这个数组中的字符串前缀,比如说用户键入“mount”并且数组包含单词“mountain”,我该如何搜索这个数组并返回相似的值。

这里是到目前为止我的代码:

public List<Interface> returnSuggestedList(String prefix) { 

     String tempPrefix = prefix; 

     suggestedPhrases.clear(); 
     //suggestedPhrases = new ArrayList<Interface>(); 
     //Vector<String> list = new Vector<String>(); 

     //List<Interface> interfaceList = new ArrayList<Interface>(); 
     Collections.sort(wordsList); 
     System.out.println("Sorted Vector contains : " + wordsList); 
     int i = 0; 
     while(i != wordsList.size()) { 




      int index = Collections.binarySearch(wordsList,prefix); 

      String tempArrayString = wordsList.get(index).toString(); 

      if(tempArrayString.toLowerCase().startsWith(prefix.toLowerCase())) { 

       ItemInterface itemInt = new Item(tempArrayString); 
       suggestedPhrases.add(itemInt); 
       System.out.println(suggestedPhrases.get(i).toString()); 
       System.out.println("Element found at : " + index); 
      } 

      i++; 
     } 



     return suggestedPhrases; 

    } 

在此先感谢。

回答

0

如果wordList是固定的(不会从一个方法调用更改为另一个),您应该将它排序到其他地方,因为排序费用很高,并将其存储为小写。

你会做一些这样的方法的其余部分:

List<String> selected = new ArrayList<String>(); 

for(String w:wordList){ 
    if(w.startsWith(prefix.toLower())) // or .contains(), depending on 
     selected.add(w);  // what you want exactly 
} 

return selected; 
2

最基本的方法是

List<String> result = new ArrayList<String>(); 
for(String str: words){ 
    if(str.contains(keyword){ 
    result.add(str); 
    } 
} 

您可以改善这个版本,如果你只用startWith,而不是contains关注,那么你可以在一个HashMap分配的话,你将不得不缩小搜索

1

由于@Jiri说,你可以使用一个耶,但如果你不想去那么远,你可以做一些简单的和有用的东西。

利用分拣

  • 如果你想的话的阵列做以前那种。不要每次都排序
  • 由于它已排序,所以您可以在列表中找到匹配的第一个和最后一个单词。使用list.subList(from,to)返回子列表。添加每一个都会更好一点。

使用预先排序结构

  • 使用TreeSet<String>用于存储字符串(在将在内部排序)。
  • 然后使用treeSet.subSet(from, true, to, false);

其中from是前缀,to是“前缀加一个字符”。例如,如果您正在寻找abcto必须是abd。如果你不想进行char转换,你可以询问treeSet.headSet(from)并迭代它直到没有更多的前缀。

如果您阅读的内容比您撰写的内容多,这将特别有用。也许订购字符串有点贵,但一旦订购,您可以非常快地找到它们(O(log n))。

不区分大小写比较

您可以提供Comparator<String>树,以表明它必须如何订购字符串设定。你可以实现它,或者在那里有一个预先建立的不区分大小写的比较器。

反正它的代码应该是:

int compare(String a, String b) { 
    return a.toLowerCase().compareTo(b.toLowerCase()); 
} 
1

另见trie数据结构。 This问题有用的信息。我认为它的getPrefixedBy()比任何你可以快速手卷的东西都更有效率。

当然,这只适用于前缀搜索。包含搜索是一个完全不同的野兽。

+0

+1 Trie是一个伟大的自动建议数据结构 – Qwerky