Java 实例 – 数组排序及元素查找(超详细)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

在 Java 编程中,数组是一种基础且重要的数据结构,它能够高效存储和管理大量同类型数据。无论是开发学生管理系统、电商平台,还是处理科学计算任务,开发者都需要掌握数组的排序与元素查找能力。本文将通过实例演示,系统讲解 Java 中数组排序与查找的核心技术,帮助读者从基础概念逐步过渡到实际应用。文中将结合代码示例、算法对比和性能分析,为不同水平的开发者提供清晰的学习路径。


一、数组基础:理解数据容器的特性

数组可以比喻为一个“有序的书架”,每个元素(书籍)都有固定的编号(索引),从 0 开始递增。例如,一个存储学生成绩的数组 int[] scores = {85, 92, 78, 95}; 中,第一个元素(索引 0)是 85,最后一个元素(索引 3)是 95。

数组的特性与操作

  • 固定长度:数组创建后长度不可变,需通过新数组复制实现动态扩展。
  • 随机访问:通过索引直接访问元素,时间复杂度为 O(1)。
  • 内存连续:所有元素在内存中连续存储,适合批量处理。
// 创建并初始化数组  
int[] numbers = new int[5]; // 长度为5的整型数组,初始值为0  
String[] names = {"Alice", "Bob", "Charlie"}; // 直接初始化字符串数组  

二、数组排序:常用算法与实现

排序是数组操作的核心场景之一。常见的排序算法包括冒泡排序、快速排序、归并排序等。我们将通过代码示例,对比不同算法的实现逻辑和性能差异。

1. 冒泡排序:相邻元素两两比较

冒泡排序通过重复遍历数组,逐步将最大值“浮”到数组末尾,如同气泡上浮过程。

public static void bubbleSort(int[] arr) {  
    int n = arr.length;  
    for (int i = 0; i < n-1; i++) {  
        for (int j = 0; j < n-i-1; j++) {  
            if (arr[j] > arr[j+1]) {  
                // 交换相邻元素  
                int temp = arr[j];  
                arr[j] = arr[j+1];  
                arr[j+1] = temp;  
            }  
        }  
    }  
}  

时间复杂度:O(n²)。适用于小规模数据或教学场景。

2. 快速排序:分而治之的高效策略

快速排序通过选择“基准值”(pivot),将数组分为两部分:小于基准值的元素和大于基准值的元素,递归处理子数组。

public static void quickSort(int[] arr, int low, int high) {  
    if (low < high) {  
        int pivotIndex = partition(arr, low, high);  
        quickSort(arr, low, pivotIndex - 1);  
        quickSort(arr, pivotIndex + 1, high);  
    }  
}  

private static int partition(int[] arr, int low, int high) {  
    int pivot = arr[high];  
    int i = low - 1;  
    for (int j = low; j < high; j++) {  
        if (arr[j] <= pivot) {  
            i++;  
            swap(arr, i, j);  
        }  
    }  
    swap(arr, i + 1, high);  
    return i + 1;  
}  

时间复杂度:平均 O(n log n),最坏 O(n²)。适合大规模数据排序。

3. Java 内置排序方法:Arrays.sort()

Java 提供了 Arrays.sort() 方法,内部根据数据类型自动选择最优算法(如 TimSort)。

int[] arr = {3, 1, 4, 1, 5};  
Arrays.sort(arr); // 排序后 arr = {1, 1, 3, 4, 5}  

三、元素查找:线性与二分法的对比

查找操作是数组应用的另一核心场景,常见方法包括线性查找和二分查找。

1. 线性查找:逐个对比

线性查找遍历数组,逐一比对目标值,时间复杂度为 O(n)。

public static int linearSearch(int[] arr, int target) {  
    for (int i = 0; i < arr.length; i++) {  
        if (arr[i] == target) {  
            return i; // 返回索引  
        }  
    }  
    return -1; // 未找到  
}  

2. 二分查找:基于有序数组的高效方法

二分查找要求数组已排序,通过不断缩小搜索范围,时间复杂度为 O(log n)。

public static int binarySearch(int[] arr, int target) {  
    int low = 0;  
    int high = arr.length - 1;  
    while (low <= high) {  
        int mid = low + (high - low) / 2;  
        if (arr[mid] == target) {  
            return mid;  
        } else if (arr[mid] < target) {  
            low = mid + 1;  
        } else {  
            high = mid - 1;  
        }  
    }  
    return -1;  
}  

使用前提:必须在排序后的数组上执行。


四、实战案例:学生管理系统

假设需要开发一个学生管理系统,需根据学号查找学生信息并按成绩排序。

案例需求

  • 输入学生姓名、学号和成绩,存储为对象数组。
  • 根据学号快速查找学生。
  • 按成绩从高到低排序并输出。

实现代码

class Student {  
    int id;  
    String name;  
    int score;  
    // 构造方法、getter/setter 省略  
}  

public class StudentManager {  
    public static void main(String[] args) {  
        Student[] students = {  
            new Student(101, "Alice", 92),  
            new Student(103, "Bob", 88),  
            new Student(102, "Charlie", 95)  
        };  

        // 按学号排序(假设学号需要升序排列)  
        Arrays.sort(students, Comparator.comparingInt(s -> s.id));  
        System.out.println("按学号排序后:");  
        for (Student s : students) {  
            System.out.println(s.id + " " + s.name);  
        }  

        // 根据学号查找  
        int targetId = 103;  
        int index = Arrays.binarySearch(students, new Student(targetId, "", 0),  
            Comparator.comparingInt(s -> s.id));  
        if (index >= 0) {  
            System.out.println("找到:" + students[index].name);  
        } else {  
            System.out.println("未找到");  
        }  
    }  
}  

五、性能分析与最佳实践

算法时间复杂度对比

算法名称最差时间复杂度平均时间复杂度适用场景
冒泡排序O(n²)O(n²)小规模数据或教学演示
快速排序O(n²)O(n log n)大规模数据排序
线性查找O(n)O(n)未排序数组的简单查找
二分查找O(log n)O(log n)排序数组的高效查找

开发者建议

  1. 优先使用内置方法:如 Arrays.sort()binarySearch(),它们经过优化且不易出错。
  2. 排序后再查找:若需频繁查找,先排序数组,再用二分查找提升效率。
  3. 避免过度优化:小规模数据(如 <1000 个元素)可直接使用冒泡排序或线性查找。

结论

掌握数组排序与元素查找是 Java 开发者必须具备的核心技能。本文通过对比多种算法的实现逻辑、性能差异和实际案例,帮助读者理解不同场景下的技术选型。无论是学生管理系统、电商商品排序,还是日志数据处理,这些技术都能为高效编程提供坚实基础。建议读者通过实际编码练习巩固知识,逐步从“理解算法原理”过渡到“灵活应用算法”。

提示:在项目中遇到复杂数据结构时,可结合 ArrayListStream API 进一步扩展功能。例如,使用 Stream.sorted() 方法实现链式排序操作,或通过 Collections.binarySearch() 处理集合类对象。

最新发布