如何在Object的List中搜索Object的属性包含字符串

时间:2013-04-07 12:14:10

标签: java android caching

我有以下案例:

  • 我有一个名为Song的对象,其中一个属性为Name
  • 我有一个sqlite数据库,可以包含多达百万条记录的歌曲。
  • 我需要进行实时搜索(在用户点击字母时,应用会直接搜索它)以获取歌曲的名称属性。

我一直在想的解决方案(我没有做过任何代码)是:

  1. 直接查询sqlite(我相信这是最糟糕的解决方案,因为我需要从sqlite中获取并将其放到Cursor
  2. 将所有sqlite记录放到List或ArrayList中,然后我不知道在哪里继续进行,因为我认为for循环不是最佳解决方案,因为我需要存储到其他List以预填充ListView
  3. 任何人都可以给我这个想法,也许只是概念,解决这个问题吗?

3 个答案:

答案 0 :(得分:2)

您应该为查询执行缓存。为此构建内存数据结构,具有级联结构(一次一个字母)。

限制特定查询的返回对象数(例如,返回最大值10)。显然,您不希望返回以字母Song开头的所有A。此外,此列表可能基于重要性(或选择频率) - 您也可以存储它。

对于缓存的内部表示,我建议这样:

public class SongCacheNode {
    private String selector;
    private Map<Character, SongCacheNode> subCaches = 
        new HashMap<Character, SongCacheNode>();
    private List<Song> selection = new ArrayList<Song>(10);
    private boolean leafNode = false;
    private boolean containsAll = false;
}

你可以建立一个树状的结构。

  • selector将存储此节点的字符串选择器(例如歌曲标题的前缀)。
  • subCaches可以存储下一个字母的下一个缓存。
  • selection可以存储已挑选的歌曲标题
  • leafNode会说缓存中没有更多数据存储,您可以使用selection,也可以SQL - 存储在containsAll
  • 如果containsAll为真,则所有可能的歌曲都存储在selection中,否则,您还必须执行SQL

此结构允许您根据歌曲标题分布构建可变深度缓存。此外,对于选择,您可以选择任何匹配,不仅是前缀匹配(例如,许多歌曲标题以'The'开头),进行不区分大小写的查询等。您可以部分缓存,以限制内存使用(例如,存储最多5个字符,或者即使有大量歌曲也不存储偶发查询) - 只需将containsAll设置为false。 / p>

答案 1 :(得分:0)

SQL lite允许full text search functionality。鉴于歌曲名称也可以使用像'thrill'|这样的部分术语进行搜索'惊悚'| '惊悚MJ',你应该去那。

虽然全文搜索会被编入索引,但根据负载,数据库可能会占用太多,在这种情况下,您可以构建trie首歌名称。可以从最后匹配节点的子节点获得所有匹配的歌曲,并且该结构将在存储器中。这应该会让它变得快速。

将歌曲详细信息加载到列表/集合中将无济于事,因为您无法进行部分匹配。 List / Set包含'thril'或者不包含'thril'。除非您使用全文搜索或像 trie 这样的内存中DS,否则无法知道部分字符串是否与数据库中的内容匹配。

答案 2 :(得分:0)

您的选项
通过将所有歌曲加载到列表中,您将加快搜索时间。但是,这将大大影响装载时间。

如果您没有将所有歌曲加载到程序中,那么您的加载时间会短得多,但搜索延迟可能会更长。

我要去哪一个

简单地说,我会选择后者。这里的优点是,您可以在用户键入时在另一个线程中进行数据库调用。多线程应用程序意味着一个线程,用户可以愉快地输入,而在另一个线程上,将发生艰巨的数据库调用,并且可以加载数据。

需要注意的一些事项/您可能想要使用的想法。

如果您的数据库有一百万首歌曲,可以肯定地说会有很多以相同字母开头的歌曲。也许没有在前几次按键上进行数据库调用会有很多原因:

  1. 每次按键后,您都不会收到大量数据。
  2. 它将减少程序必须处理的数据量,从而降低性能。
  3. 这将为客户端提供不那么令人生畏的用户界面。想象一下,输入一首歌,看到一张十万首歌曲的名单无处不在。它没有流动的可用性。

另一个想法是在每个查询上缓存数据。考虑到这一点,可以非常快速地获得相同的数据。