使用右集合在 Java 中编写索引

本文探讨了在Java中使用索引来优化大规模数据搜索的策略。通过实例展示了如何利用HashMap、TreeSet等数据结构创建索引,以实现按ID、姓名、年龄等条件的快速查询。同时,也讨论了索引的优缺点,包括在数据变更时的维护成本,并提出在某些实时应用中可能需要自定义索引。
摘要由CSDN通过智能技术生成

什么是索引以及如何在Java中使用它

索引是一种便于在数据中进行搜索的结构。是一个非常通用的术语,不属于某些语言或数据库。为了解释它,让我们创建一种方法来搜索用户的特定条件,如姓名,ID,出生日期等。

在数百万个用户条目中快速搜索

假设我们有 100 万用户。作为一项要求,我们必须通过特定条件向搜索用户公开 API。显然,简单的迭代会花费太多时间。因此,让我们使用索引(或者只是通过预先生成一些在API调用期间加速查找的数据)来解决这个问题。因此,首先让我们定义我们的用户类和搜索界面:

 

仅使用默认 Java 集合

在我们的服务中,我们只使用默认的Java集合。如果您不熟悉它们并且不知道它们使用什么数据结构,那么阅读起来会有点困难。其中一个主要思想是仅使用经典的Java集合来快速创建索引。同时,创建自己的索引并不困难。

按 ID 搜索唯一用户

作为第一个实现的API,我们创建了索引,以便快速访问唯一用户。最简单的方法是将每个用户ID保留为键,并将用户保留为HashMap中的值。

 

平均而言,这样的解决方案将提供恒定的复杂性,这实际上是一个完美的案例。

按非唯一名称搜索用户

现在情况更加复杂。用户名不是唯一的,我们希望返回特定名称的用户列表。解决方案将是相同的 - 具有用户名的哈希映射和具有相同名称的用户列表。复杂性仍然相同 - 恒定

 

按年龄搜索用户(小于指定值)

现在,当请求的期限未知时,我们创建一个索引,并且我们无法为每个键创建一个列表(这将花费大量内存,例如1M列表)。因此,经典的搜索解决方案是基于树的索引。因此,对于我们的情况,我们使用 TreeSet 集合。树搜索过程将比恒定的慢,但仍然是可以接受的。

树集隐藏在二叉树中。此树构建树在传递给构造函数的比较器中定义。基本上,比较器只需要比较两个节点。如果比较器返回 0,则表示将删除其中一个节点。在我们的例子中,我们保留所有用户,所以实现将如下所示:

 

在我们获取年龄小于指定的所有用户之前,我们必须再次查看此树是如何构建的:

  • 我们使用 age 来决定节点位置(如果比较器返回负数,则返回左数,如果为正数 - 右,如果为 0 则不添加节点)
  • 在我们的例子中,所有用户都必须留在树中。因此,当年龄相同时,比较器应返回0并跳过一个用户。而不是它,我们通过id(这是唯一的)进行比较

为了澄清内部结构,让我们画一个可能的树:

 

因此,现在如果我们获取用户年龄小于14的用户,我们必须找到最“正确”的节点。从图像中,您可以意识到最“正确”是具有最大id(即整数.MAX)的那个。现在意识到这一点,我们可以使用TreeSet中的方法:headset

 

此方法将返回年龄小于 maxAge 且日志复杂性的所有用户。

按年龄搜索用户(日期之间)

几乎在前面显示的方式中,我们可以使用 TreeSet 来构建基于年龄的索引。在这种情况下,唯一的区别是如何获取日期之间的子集。与前面的示例一样,我们还需要使用整数最小值和最大值以及子集方法来选择大多数“左”和“右”节点:

 

更多示例

到目前为止,所展示的内容看起来非常明显。让我们想象一个更复杂的情况,当客户端需要获取名称以3个指定字符开头的所有用户时。当您开始在Google中输入时,您是否已经看到了这样的功能,并且它几乎可以立即向您显示结果?

 

如何实施?以同样的方式准备索引。

所以很快的要求是:

  • 客户端请求 3 个字符,API 返回名称以它开头的所有用户
  • API响应应该很快(好吧,没有固定的时间要求,而是意味着复杂性必须是恒定的,或者至少是对数的)

同样,使用HashMap,我们可以轻松创建此类索引。我们唯一需要的是使用每个名称的前3个字符并保存它们:

 

此示例与 getUsersByName 几乎完全相同,但我用它来揭示具有自动完成功能的已知功能是如何工作的。

没有Java集合的自定义索引值得吗?

简短的答案 - 不。默认集合是众所周知且可靠的。它们为您提供了恒定的和记录的复杂性。这绰绰有余,但在某些情况下,特别是对于实时应用程序,您可以编写自己的索引。

索引 缺点

索引带来性能,但您必须为此付费。在所有缺点中,主要有两个:

 

在我们的示例中,我们假设不会添加或删除任何用户。实际上,这样的数据更改可能代价高昂(并非所有索引,例如树或基于链接的结构在每次更新时都不会消耗太多时间和内存)。因此,您必须记住,在重新计算索引时,您的API将被搁置(或提供过时的数据)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值