【问题标题】:Data structure for search engine in JAVA?JAVA中搜索引擎的数据结构?
【发布时间】:2009-10-13 08:50:50
【问题描述】:

我是 MCS 的二年级学生。我正在用 Java 做一个项目,其中有不同的图像。为了存储 IMAGE-1 的描述,我有一个名为 IMAGE-1 的 ArrayList,对于 IMAGE-2 ArrayList IMAGE-2 n 类似......

现在我需要开发一个搜索引擎,我需要在其中找到描述与搜索引擎中输入的单词匹配的所有图像............

FOR EX 如果我输入“计算机”,那么我应该能够找到描述中包含“计算机”的所有图像。

所以我的问题是......

我应该如何有效地做到这一点?
我应该如何维护所有这些 ArrayList 因为我可以拥有 100 个 这样的...?还是我应该使用另一个 数据结构而不是ArrayList?

【问题讨论】:

    标签: java data-structures


    【解决方案1】:

    一个简单的实现是tokenize描述并使用Map<String, Collection<Item>>来存储一个token的所有项目。

    建筑:

    for(String token: tokenize(description)) map.get(token).add(item)
    

    (需要一个集合,因为可以为一个令牌找到多个条目。代码中缺少集合的初始化。但想法应该很清楚。)

    用途:

    List<Item> result = map.get("Computer")
    

    在这种情况下,通用的 HashMap 实现并不是最有效的。当您开始遇到内存问题时,您可以查看更高效的树实现(例如 radix trees - implementation)。

    下一步可能是使用一些(内存中的)数据库。这些可以是相关的 (HSQL) 也可以不是 (Berkeley DB)。

    【讨论】:

    • 你说的没什么新意。看我的帖子。
    • 我不明白你想说什么:tag != token。如果它被称为标签,它应该是一个标签(en.wikipedia.org/wiki/Tag_%28metadata%29)。标记听起来像是用户决定链接哪些项目和标签。
    • 在您的情况下,项目/图像列表将映射到令牌/密钥。就我而言,它是相同的,但我说它是标签而不是令牌。当我们在这里 SO 时,标记我们的帖子,单个标签可以保存帖子列表。所以,我相信我使用的术语显然是有效的。
    • 可能是我没有很好地表达我的想法。或者说我选错了词。无论如何,但事实是我也说过同样的话。所以,像我一样思考 +1 :)。
    • 如您所见,标签集不是标记化的描述,而是用户分配的元数据。这是两个完全不同的概念。
    【解决方案2】:

    如果您有少量图像和简短描述(String.indexOf() 搜索单词(即数组中的一个条目 == 一个完整的图像描述)。这对于例如少于 10,000 张图像来说已经足够高效了。

    使用toLowerCase() 折叠字符的大小写(这样用户在键入“计算机”时会找到“计算机”)。 String.indexOf() 也适用于短词(使用“comp”查找“Computer”或“compare”)。

    如果您有很多图片和冗长的描述,并且/或者您想让您的用户在搜索时感到舒适(就像 Google 所做的那样),那么请使用 Lucene

    【讨论】:

    • Lucene 是一头大象,相信我。但确实值得一试。
    • 谢谢...但是描述可能非常大,即超过 1000 行,所以可以将它存储在简单的数组中吗?
    • 使用字符串有什么问题?
    • 该数组需要更多内存,而且搜索速度会变慢,为什么要使用一个呢?
    【解决方案3】:

    没有简单易用的数据结构支持高效的全文搜索。

    但是你真的需要效率吗?这是桌面应用程序还是网络应用程序?在前一种情况下,不用担心效率,现代 CPU 可以在几分之一秒内搜索兆字节的文本 - 只需使用 String.contains()(或允许更灵活搜索的正则表达式)查看所有描述。

    如果您确实需要效率(例如对于一个多人可以同时进行搜索的网络应用),请查看Apache Lucene

    至于您的 ArrayList,使用一个来描述单个图像似乎很奇怪。为什么是列表,索引代表什么?线?如果是这样,除非你真的需要直接访问行,用一个简单的字符串替换列表 - 它可以包含换行符就好了。

    【讨论】:

    • 这是一种奇怪的方法。试试蛮力。如果失败,请使用这个巨大的库(Lucene)。中间有一两个解决方案。
    • 引用一些工作量不大或用处有限(将单词映射到文本偏移量在复合单词上失败)。
    • 一个简单的解决方案可以是:将描述标记化,for(token: tokenize(descr)) map.put(token, item)。这会消耗一些内存,但可能是一个有效的解决方案。取决于约束。
    • 正如我所写:复合词失败。大多数用户不会对这种限制感到满意。
    • 可以根据需要进行标记。如果您开始构建自己的词干,是时候使用 Lucene。但问题在于找到直接命中(简单的标记,没有词干)。
    【解决方案4】:

    我建议您使用 Hashtable 类或将您的内容组织到树中以优化搜索。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-09-21
    相关资源
    最近更新 更多