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返回值解析:

有道智云AI开放平台
有道智云AI开放平台

有道智云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中高效地解决了在自定义对象列表中查找特定字段“大于等于”的最近值的问题,为处理大数据量场景提供了可靠的解决方案。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

825

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

724

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

728

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

395

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

398

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

445

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

428

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16881

2023.08.03

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
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号