当前位置: 首页
编程语言
怎么通过 Collections.binarySearch() 在自定义对象数组列表中进行高效模糊匹配

怎么通过 Collections.binarySearch() 在自定义对象数组列表中进行高效模糊匹配

热心网友 时间:2026-05-06
转载

怎么通过 Collections.binarySearch() 在自定义对象数组列表中进行高效模糊匹配

怎么通过 Collections.binarySearch() 在自定义对象数组列表中进行高效模糊匹配

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

开门见山地说,Collections.binarySearch() 这个工具本身并不支持模糊匹配。它的设计初衷就是进行精确的二分查找,并且要求列表必须已经按照严格一致的排序规则升序排列。那么,如果想在自定义对象列表里实现诸如“姓名前缀匹配”、“数值范围筛选”这类模糊查询,是不是就没辙了?当然不是。关键在于,你不能指望它一步到位,而是需要结合预处理、合理排序和后续的局部扫描,来高效地缩小搜索范围。

前提:必须先按模糊匹配依据排序

这里有个常见的误解,以为“模糊”就等于“无序遍历”。恰恰相反,高效的模糊匹配往往是“先精准定位大致区间,再在区间内精细检查”。举个例子:

  • 你想找所有姓名以 "Zha" 开头的用户 → 那么列表就必须按 name 字段的字典序升序排列;
  • 你想筛选年龄在 [25, 35] 区间的用户 → 列表就需要按 age 字段升序排列;
  • 至于想找与某个关键词编辑距离 ≤1 的字符串 —— 这种情况二分法就力不从心了,得考虑换用 Trie 树或 BK-tree 这类专门的数据结构。

这里有个至关重要的细节:你排序时使用的 Comparator,其比较逻辑必须和后续的模糊匹配逻辑完全对齐。比如按姓名排序,代码通常长这样:

List list = ... ;
list.sort(Comparator.comparing(p -> p.getName()));

用 binarySearch 找到“插入点”,界定模糊区间

这才是技巧的核心所在。利用好 binarySearch 返回的负值(其公式为 -(insertionPoint) - 1),我们可以快速定位模糊查询的边界。

以查找所有 name.startsWith("Zha") 的用户为例,具体操作分几步走:

  • 首先,构造一个“虚拟查询对象”,比如 Person key = new Person("Zha", ...)
  • 接着,调用 int pos = Collections.binarySearch(list, key, nameComparator)
  • 如果 pos >= 0,那真是巧了,说明列表里存在一个姓名完全等于 "Zha" 的记录(概率很小),你可以从这个位置向左右两边扩展检查;
  • 更常见的情况是 pos < 0。这时,insertionPoint = -pos - 1,这个值意味着:所有姓名 >= "Zha" 的元素,都从索引 insertionPoint 开始存放。这就是我们模糊匹配的起始下界
  • 然后,我们需要确定结束上界。再构造一个虚拟对象,其姓名为 "Zhb"(这是字典序中紧接在 "Zha" 之后的最小字符串),同样用 binarySearch 查找,得到另一个插入点 endPoint
  • 至此,候选区间就锁定为 [insertionPoint, endPoint)。最后,你只需要遍历这个通常远小于全列表的子区间,逐一判断 startsWith("Zha") 即可,效率提升立竿见影。

数值范围模糊(如 age ∈ [25,35])更直接

对于数值型的范围查询,这个方法用起来更加直观。假设列表已按 age 排序:

  • binarySearch(list, new Person(25, ...), ageComparator) 可以直接得到年龄 ≥25 的起始位置;
  • 再用 binarySearch(list, new Person(36, ...), ageComparator) 得到年龄 >35 的起始位置(因为36是第一个不满足 ≤35 的值);
  • 这两个位置之间的所有元素,其年龄都必然落在 [25, 35] 这个闭区间内,无需再进行任何额外的过滤判断,结果直接可用。

注意边界与自定义 Comparator 的一致性

方法虽好,但有几个关键陷阱必须警惕,否则很容易前功尽弃:

  • Comparator 必须纯粹:比较逻辑必须完全忽略模糊匹配中不关心的字段。如果你按姓名排序,却在比较器里还偷偷比较了年龄,排序结果就会错乱,二分查找必然失效。
  • 虚拟对象要“瘦身”:构造用于查询的虚拟对象时,只设置用于排序的那个关键字段(比如只设 name="Zha"),其他字段可以设为 null 或任意值,避免无关字段干扰比较逻辑。
  • 自然排序需谨慎:如果对象实现了 Comparable 接口,务必确保其 compareTo() 方法的行为与你想要进行模糊匹配的维度严格一致。
  • 二分查找不保序binarySearch 在遇到重复值时,不保证返回的是第一个或最后一个匹配项,它只定位到“某一个”匹配位置或插入点。因此,在定位到的区间内如果存在重复值,可能还需要向邻近位置进行简单的线性扫描来确定完整范围。
来源:https://www.php.cn/faq/2425096.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
Go语言嵌套结构体与数组建模指南实现清晰可维护JSON序列化

Go语言嵌套结构体与数组建模指南实现清晰可维护JSON序列化

Go语言中嵌套结构体与数组的高级建模实践:清晰、可维护、符合JSON序列化规范 本文详解如何为复杂JSON结构(如含多层嵌套对象与数组)设计Go结构体,推荐显式命名类型替代匿名结构,结合导出字段、精准struct tag及构造函数,提升可读性、可测试性与跨包可用性。 在Go语言中处理复杂的JSON数

时间:2026-05-06 18:07
Python异步编程中全局变量安全吗ContextVars上下文变量详解

Python异步编程中全局变量安全吗ContextVars上下文变量详解

异步函数中直接读写全局变量会导致协程间上下文污染,引发用户ID错乱、权限校验错误等问题;threading local在asyncio中失效,因协程共享同一线程;应使用ContextVar配合set get reset确保上下文隔离。 异步函数里直接读写全局变量会出什么问题 不安全,而且非常容易踩坑

时间:2026-05-06 18:07
Python集成测试指南使用pytest搭建服务器端到端验证方法

Python集成测试指南使用pytest搭建服务器端到端验证方法

pytest集成测试的核心挑战在于:动态分配端口以避免冲突,确保服务器完全就绪后再发起请求,实现数据库的彻底隔离,为JSON请求设置正确的请求头,并在测试结束后清理资源,防止持续集成(CI)环境失败。 pytest 启动测试服务器时端口被占怎么办 在本地运行集成测试时,你是否也经常被 Address

时间:2026-05-06 18:06
Python数据加权计算指南np.average函数实操详解

Python数据加权计算指南np.average函数实操详解

np a verage()加权计算:避开那些让你结果变nan的“坑” 在数据处理中,加权平均是再常见不过的操作,但np a verage()这个看似简单的函数,却暗藏玄机。一个不小心,算出来的结果全是nan,或者直接抛出AxisError,让人摸不着头脑。问题往往就出在权重参数weights的设置上

时间:2026-05-06 18:06
Go语言go run命令无响应问题排查与解决方案详解

Go语言go run命令无响应问题排查与解决方案详解

Go 语言 go run 命令无输出且不退出的排查与解决 Go 程序使用 go run main go 时无控制台输出、进程不退出,常见于 Windows 平台下安全软件(如 Comodo)对 go exe 的自动隔离行为,而非代码或环境配置错误。 遇到 go run main go 命令执行后,终

时间:2026-05-06 18:06
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜
热门教程
更多
  • 游戏攻略
  • 安卓教程
  • 苹果教程
  • 电脑教程