0

0

在Java集合中高效查找自定义对象中“大于等于”的最近值

心靈之曲

心靈之曲

发布时间:2025-07-14 21:04:06

|

614人浏览过

|

来源于php中文网

原创

在java集合中高效查找自定义对象中“大于等于”的最近值

本文旨在探讨如何在Java中高效地从包含自定义对象的列表中查找指定字段的“大于等于”的最近值。针对拥有大量记录且数据已按特定字段排序的场景,我们将介绍如何利用Collections.binarySearch方法,结合自定义比较器,实现对列表的对数时间复杂度查找,从而避免全量迭代,显著提升查找效率。

问题背景与挑战

在实际开发中,我们经常会遇到需要在一个包含自定义对象的列表中查找特定元素的需求。例如,假设我们有一个Row对象列表,每个Row对象包含两个整型字段a和b:

class Row {
   int a;
   int b;
}

已知该列表的特性是:如果按字段a排序,则字段b也会自动排序。我们的目标是编写一个函数find(int x, List rows),该函数需要找出列表中字段b的值“紧跟在x之后”(即第一个大于或等于x)的Row对象。当记录数量达到1000条甚至更多时,简单的线性迭代查找效率低下。因此,我们需要一种更高效的数据结构或查找方法。

解决方案:利用Collections.binarySearch

Java的Collections.binarySearch方法是解决此类问题的理想选择。它利用二分查找算法,能够在已排序的列表中以对数时间复杂度(O(log N))进行查找,远优于线性迭代(O(N))。

1. 定义Row类与比较器

首先,我们需要完善Row类,使其包含构造函数、getter方法以及toString方法,以便于调试和输出。更重要的是,为了让Collections.binarySearch能够根据b字段进行查找,我们需要定义一个Comparator。

立即学习Java免费学习笔记(深入)”;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

static class Row {
    int a, b;

    public int getA() { return a; }
    public int getB() { return b; }

    Row(int a, int b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public String toString() {
        return "Row(" + a + ", " + b + ")";
    }
}

// 定义一个基于b字段进行比较的比较器
static final Comparator ORDER_BY_B = Comparator.comparing(Row::getB);

Comparator.comparing(Row::getB)是一种简洁的Lambda表达式写法,用于创建一个根据Row对象的b字段进行升序比较的比较器。

2. 实现查找函数

核心的查找逻辑封装在find方法中。这个方法将接收一个目标整数x和一个Row对象列表rows。

static Row find(int x, List rows) {
    int size = rows.size();
    // 使用Collections.binarySearch进行查找
    // 传入一个“虚拟”的Row对象作为查找键,其b值为x
    int i = Collections.binarySearch(rows, new Row(0, x), ORDER_BY_B);

    // 解析binarySearch的返回值来确定目标元素的索引
    int index;
    if (i >= 0) {
        // 如果i >= 0,表示找到了精确匹配的元素,直接使用该索引
        index = i;
    } else {
        // 如果i < 0,表示未找到精确匹配的元素。
        // binarySearch返回的是 (-(插入点) - 1)。
        // 插入点是该元素在列表中应插入的位置,即第一个大于它的元素的索引。
        // 所以,-i - 1 就是这个插入点。
        int insertionPoint = -i - 1;

        // 处理边界情况:如果x大于列表中所有b值,插入点将是列表大小
        // 此时我们希望返回最后一个元素
        if (insertionPoint >= size) {
            index = size - 1;
        } else {
            // 否则,插入点就是我们寻找的第一个大于或等于x的元素的索引
            index = insertionPoint;
        }
    }
    // 返回找到的Row对象
    return rows.get(index);
}

binarySearch返回值解析:

AIPAI
AIPAI

AI视频创作智能体

下载
  • 如果找到与搜索键精确匹配的元素,则返回其索引(i >= 0)。
  • 如果未找到,则返回(-(插入点) - 1)。这里的“插入点”是指如果将搜索键插入到列表中以保持排序顺序,它应该被插入的索引。例如,如果所有元素都小于搜索键,插入点将是list.size()。

索引计算逻辑解释:

我们的目标是找到第一个b值大于或等于x的Row。

  1. i >= 0: 这意味着x的精确值在列表中找到了。那么,i就是我们需要的索引。
  2. i : 这意味着x的精确值未找到。
    • 通过insertionPoint = -i - 1,我们得到了x在列表中应该被插入的位置。这个位置上的元素(如果存在)就是第一个b值大于x的元素。
    • 边界情况:insertionPoint >= size: 这发生在x大于列表中所有Row的b值时。此时,binarySearch会返回-(size + 1)。根据我们的需求,如果x比所有元素都大,我们通常会返回列表中的最后一个元素作为“最近的”值。因此,我们将index设置为size - 1。
    • 其他情况:insertionPoint : 这意味着insertionPoint指向了列表中第一个b值大于x的元素。这就是我们所寻找的“大于或等于”的最近值。

3. 示例与测试

为了验证上述实现,我们可以创建一个main方法来测试find函数。

public static void main(String[] args) {
    // 原始数据,注意它已经按a排序,并且b也随之排序
    List rows = Arrays.asList(
        new Row(20, 2),
        new Row(40, 4),
        new Row(50, 5),
        new Row(70, 7));

    // 确保列表是按b排序的,这是binarySearch的前提
    // 虽然原始问题说按a排序b也排序,但为了严谨性,这里显式排序
    List orderByB = rows.stream().sorted(ORDER_BY_B).collect(Collectors.toList());

    System.out.println("Sorted list by B: " + orderByB);

    // 测试不同x值
    for (int i = 0; i < 9; ++i) {
        System.out.println("find " + i + " : " + find(i, orderByB));
    }
}

运行结果:

Sorted list by B: [Row(20, 2), Row(40, 4), Row(50, 5), Row(70, 7)]
find 0 : Row(20, 2)
find 1 : Row(20, 2)
find 2 : Row(20, 2)
find 3 : Row(40, 4)
find 4 : Row(40, 4)
find 5 : Row(50, 5)
find 6 : Row(70, 7)
find 7 : Row(70, 7)
find 8 : Row(70, 7)

从输出可以看出,当x为0、1、2时,返回的是b值为2的Row(20, 2),因为它是第一个b值大于等于x的元素。当x为3时,返回Row(40, 4),以此类推。当x为8时,由于列表中没有b值大于等于8的元素,它返回了最后一个元素Row(70, 7),符合我们对“大于等于”且处理越界情况的预期。

注意事项与总结

  1. 列表排序是前提:Collections.binarySearch要求被搜索的列表必须是已排序的。在本例中,列表必须按照ORDER_BY_B这个Comparator进行排序。如果原始数据未排序,则需要先进行排序(例如使用list.sort(ORDER_BY_B)),这会引入O(N log N)的时间复杂度。
  2. 查找键的构造:在binarySearch中,我们传入了一个new Row(0, x)作为查找键。这里的a字段的值(0)是无关紧要的,因为我们的Comparator只关注b字段。
  3. 对数时间复杂度:一旦列表排序完成,每次查找操作都将在O(log N)时间内完成,这对于包含大量记录的列表(如1000条)来说,效率提升是巨大的。
  4. “大于等于”的语义:本教程实现的“最近值”是指列表中第一个b值大于或等于给定x的元素。如果x大于列表中所有元素的b值,则返回最后一个元素。这需要根据具体业务需求进行调整。

通过以上方法,我们成功地利用Collections.binarySearch在Java中高效地解决了在自定义对象列表中查找特定字段“大于等于”的最近值的问题,为处理大数据量场景提供了可靠的解决方案。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

395

2023.09.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

463

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

544

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

113

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

200

2025.08.29

lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

208

2023.09.15

python lambda函数
python lambda函数

本专题整合了python lambda函数用法详解,阅读专题下面的文章了解更多详细内容。

191

2025.11.08

Python lambda详解
Python lambda详解

本专题整合了Python lambda函数相关教程,阅读下面的文章了解更多详细内容。

55

2026.01.05

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

8

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号