【问题标题】:Efficient SearchView suggestions in AndroidAndroid 中的高效 SearchView 建议
【发布时间】:2026-02-14 03:10:01
【问题描述】:

我的 ActionBar 中有一个 SearchView,在用户键入字符时显示建议。 我的建议存储在 String ArrayList 中,如下所示:

private ArrayList<String> mSuggestions;

然后我的搜索功能会根据查询的文本显示建议。

public boolean onQueryTextChange(String newText) {
    mSuggestions.clear();
    for(MyObject o : mObjects)
        if(o.getName().contains(newText))
            mSuggestions.add(o.getName());

    return false;
}

它有 O(n) 的效率,因为它遍历数组来搜索查询的单词。因此,当 mSuggestions.size() 增长时,它会变得缓慢且效率低下。

我想使用另一个比 ArrayList 更高效的容器来进行搜索 O(log(n)),但还没有找到最合适的容器。

有人对此有什么建议吗?

提前致谢。

【问题讨论】:

  • 要获得真正有效的结果,您可以查看 SQLite FTS3 虚拟表,但它很复杂,并且第一次构建表需要时间,具体取决于数据库记录的数量。谷歌 FTS3。我认为 Android 开发网站也有一个如何使用它的示例。
  • 听起来很有趣。我正在寻找的是更高层次的东西,比如使用另一个容器而不是 ArrayList 或任何算法。感谢您的回复。

标签: android actionbarsherlock performance searchview


【解决方案1】:

由于您正在进行子字符串搜索,您可以考虑使用 HashMap 将每个可能的子字符串映射到包含该子字符串的对象列表 (HashMap&lt;String, List&lt;MyObject&gt;&gt;)。这假设您的 mObjects 列表未针对每个查询更新(例如,如果您正在执行网络请求以根据查询加载结果)并且您能够预先计算或多或少保持静态的数据结构。然后您的查找将在 O(1) 中完成,但您需要支付空间效率来存储所有子字符串。您的代码如下所示:

private Map<String, List<MyObject>> mObjectLookupMap = 
    new HashMap<String, List<MyObject>>();

// precompute lookup map with all possible substrings

public boolean onQueryTextChange(String newText) {
    mSuggestions.clear();

    if (mObjectLookupMap.containsKey(newText)) {
       for (MyObject o : mObjectLookupMap.get(newText))
         mSuggestions.add(o.getName());
    }

    return false;
}

更节省空间的解决方案可能是使用Trie 来存储子字符串。那么您的查找时间将按照最长的 MyObject 名称(即子字符串树的深度)排序。

【讨论】: