java 排序 详解

Java 提供了多种方式对数据进行排序,包括数组和集合的排序。排序在日常开发中非常常见,以下将从排序算法的基本原理、Java 中的内置排序方法以及自定义排序三方面进行详解。


1. 排序的基本概念

排序是将一组数据按特定顺序排列的过程,常见顺序包括:

  • 升序:从小到大排列(如:1, 2, 3, ...)。
  • 降序:从大到小排列(如:10, 9, 8, ...)。

常见排序算法及其时间复杂度

排序算法 时间复杂度(平均) 时间复杂度(最坏) 空间复杂度 稳定性
冒泡排序 (Bubble Sort) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1) 稳定
插入排序 (Insertion Sort) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1) 稳定
选择排序 (Selection Sort) O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1) 不稳定
快速排序 (Quick Sort) O ( n log ⁡ n ) O(n \log n) O(nlogn) O ( n 2 ) O(n^2) O(n2) O ( log ⁡ n ) O(\log n) O(logn) 不稳定
归并排序 (Merge Sort) O ( n log ⁡ n ) O(n \log n) O(nlogn) O ( n log ⁡ n ) O(n \log n) O(nlogn) O ( n ) O(n) O(n) 稳定
堆排序 (Heap Sort) O ( n log ⁡ n ) O(n \log n) O(nlogn) O ( n log ⁡ n ) O(n \log n) O(nlogn) O ( 1 ) O(1) O(1) 不稳定

2. Java 中的内置排序方法

Java 提供了丰富的内置排序方法,主要通过 ArraysCollections 两个工具类实现。

(1) 使用 Arrays.sort 方法(针对数组)

用法
  • 基础类型数组:直接使用。
  • 引用类型数组:可以传入自定义比较器。
示例代码
java 复制代码
import java.util.Arrays;

public class ArraySortExample {
    public static void main(String[] args) {
        // 基础类型数组排序
        int[] numbers = {5, 2, 8, 1, 3};
        Arrays.sort(numbers); // 默认升序
        System.out.println("基础类型排序后:" + Arrays.toString(numbers));

        // 引用类型数组排序
        String[] words = {"apple", "banana", "cherry", "date"};
        Arrays.sort(words); // 默认按字典序排序
        System.out.println("引用类型排序后:" + Arrays.toString(words));

        // 自定义排序(降序)
        Arrays.sort(words, (a, b) -> b.compareTo(a));
        System.out.println("自定义排序后:" + Arrays.toString(words));
    }
}
输出结果
基础类型排序后:[1, 2, 3, 5, 8]
引用类型排序后:[apple, banana, cherry, date]
自定义排序后:[date, cherry, banana, apple]
特点
  • Arrays.sort 使用 双轴快速排序 (Dual-Pivot Quicksort)实现,时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn)。
  • 对基础类型排序效率极高,但对引用类型需要更多内存。

(2) 使用 Collections.sort 方法(针对集合)

用法
  • 专为 List 设计(如 ArrayListLinkedList 等)。
  • 可以使用默认排序(元素需实现 Comparable 接口)或自定义比较器。
示例代码
java 复制代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionSortExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(5);
        numbers.add(2);
        numbers.add(8);
        numbers.add(1);
        numbers.add(3);

        // 默认升序排序
        Collections.sort(numbers);
        System.out.println("默认排序后:" + numbers);

        // 自定义排序(降序)
        Collections.sort(numbers, (a, b) -> b - a);
        System.out.println("自定义排序后:" + numbers);
    }
}
输出结果
默认排序后:[1, 2, 3, 5, 8]
自定义排序后:[8, 5, 3, 2, 1]
特点
  • Collections.sort 内部调用 Listsort 方法,底层使用 TimSort 算法。
  • 稳定排序,适合复杂对象的排序。

(3) 使用 List.sort 方法

从 Java 8 开始,List 接口新增了 sort 方法,可以直接传入比较器。

示例代码
java 复制代码
import java.util.ArrayList;
import java.util.List;

public class ListSortExample {
    public static void main(String[] args) {
        List<String> words = new ArrayList<>();
        words.add("apple");
        words.add("banana");
        words.add("cherry");
        words.add("date");

        // 默认升序
        words.sort(String::compareTo);
        System.out.println("默认排序后:" + words);

        // 自定义排序(按长度降序)
        words.sort((a, b) -> b.length() - a.length());
        System.out.println("按长度降序排序后:" + words);
    }
}
输出结果
默认排序后:[apple, banana, cherry, date]
按长度降序排序后:[banana, cherry, apple, date]

3. 自定义排序

对于复杂对象,需要使用 ComparableComparator 来定义排序规则。

(1) 使用 Comparable 接口

Comparable 接口用于定义自然排序,需实现其 compareTo 方法。

示例代码
java 复制代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Student implements Comparable<Student> {
    String name;
    int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public int compareTo(Student other) {
        return this.score - other.score; // 按分数升序
    }

    @Override
    public String toString() {
        return name + ": " + score;
    }
}

public class ComparableExample {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 85));
        students.add(new Student("Bob", 92));
        students.add(new Student("Charlie", 78));

        Collections.sort(students);
        System.out.println("按分数升序排序:" + students);
    }
}
输出结果
按分数升序排序:[Charlie: 78, Alice: 85, Bob: 92]

(2) 使用 Comparator 接口

Comparator 接口用于定义外部排序规则,可以灵活调整排序逻辑。

示例代码
java 复制代码
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

class Student {
    String name;
    int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public String toString() {
        return name + ": " + score;
    }
}

public class ComparatorExample {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 85));
        students.add(new Student("Bob", 92));
        students.add(new Student("Charlie", 78));

        // 按分数降序排序
        students.sort((a, b) -> b.score - a.score);
        System.out.println("按分数降序排序:" + students);

        // 按名字字母升序排序
        students.sort(Comparator.comparing(s -> s.name));
        System.out.println("按名字升序排序:" + students);
    }
}
输出结果
按分数降序排序:[Bob: 92, Alice: 85, Charlie: 78]
按名字升序排序:[Alice: 85, Bob: 92, Charlie: 78]

4. 常见排序陷阱与优化

  1. 稳定性问题
    • 对于需要保持原始顺序的排序,使用稳定排序算法(如 Collections.sortTimSort)。
  2. 性能优化
    • 对小规模数组使用插入排序或冒泡排序。
    • 对大规模数据使用快速排序或归并排序。
  3. **
    避免多次比较**:
    • 使用 Comparator.comparing 链式调用时避免重复字段比较。

5. 总结

  • 数组排序 :使用 Arrays.sort,适合基础类型和简单对象。
  • 集合排序 :使用 Collections.sortList.sort,适合复杂对象和灵活排序需求。
  • 自定义排序 :通过 ComparableComparator 实现,灵活定义规则。
  • 排序算法:根据数据规模和需求选择合适的排序算法。

Java 内置的排序方法效率高、使用方便,但理解其底层原理和优化策略可以帮助开发者更好地应对复杂排序需求。

相关推荐
召唤神龙6 分钟前
java调用代理ip:轻松实现高效网络请求,提升开发效率
java
小扳23 分钟前
Web 毕设篇-适合小白、初级入门练手的 Spring Boot Web 毕业设计项目:电影院后台管理系统(前后端源码 + 数据库 sql 脚本)
java·前端·数据库·spring boot·mysql·spring·课程设计
吃一克鹅蛋26 分钟前
Spring 框架环境搭建
java·后端·spring
百香果果ccc38 分钟前
Java中的File和IO流
java·开发语言·log4j
委婉待续1 小时前
java抽奖系统(一)
java·开发语言
阿史大杯茶1 小时前
CodeTON Round 9 (Div. 1 + Div. 2, Rated, Prizes! ABCDE题) 视频讲解
数据结构·c++·算法
chusheng18402 小时前
Java基于SpringBoot+Vue的藏区特产销售平台
java·vue.js·spring boot·藏区特产销售平台·特产销售平台
赔罪2 小时前
C 语言变量说明符
c语言·开发语言·c++·学习·算法·objective-c
Java学长-kirito2 小时前
springboot/ssm网购平台管理系统Java在线购物商城管理平台web电商源码
java·前端·spring boot
A Man Of Mould2 小时前
【数据结构】—— 堆
数据结构·算法