杰瑞科技汇

Java ArrayList如何排序?

在 Java 中,对 ArrayList 进行排序有多种方法,主要可以分为以下几类:

Java ArrayList如何排序?-图1
(图片来源网络,侵删)
  1. 基本数据类型和自定义对象的自然排序
  2. 自定义排序规则
  3. 并行排序

下面我将详细介绍这些方法,并提供完整的代码示例。


基本数据类型和自定义对象的自然排序

对于基本数据类型(如 Integer, Double)或者实现了 Comparable 接口的自定义对象,可以直接使用 Collections.sort() 方法,这种方式会按照对象定义的“自然顺序”进行排序。

示例1:对 ArrayList<Integer> 排序

这是最简单的情况,Integer 类型已经实现了 Comparable 接口。

import java.util.ArrayList;
import java.util.Collections;
public class SortArrayListExample {
    public static void main(String[] args) {
        // 1. 创建一个 ArrayList
        ArrayList<Integer> numbers = new ArrayList<>();
        numbers.add(5);
        numbers.add(1);
        numbers.add(9);
        numbers.add(3);
        numbers.add(7);
        System.out.println("排序前的 ArrayList: " + numbers);
        // 2. 使用 Collections.sort() 进行排序(默认升序)
        Collections.sort(numbers);
        System.out.println("排序后的 ArrayList (升序): " + numbers);
    }
}

输出:

Java ArrayList如何排序?-图2
(图片来源网络,侵删)
排序前的 ArrayList: [5, 1, 9, 3, 7]
排序后的 ArrayList (升序): [1, 3, 5, 7, 9]

示例2:对自定义对象进行自然排序

如果你的类(Student)想要使用 Collections.sort() 进行排序,那么这个类必须实现 Comparable 接口,并重写 compareTo() 方法。

compareTo() 方法的规则:

  • 返回一个负整数:表示当前对象小于被比较的对象。
  • 返回零:表示当前对象等于被比较的对象。
  • 返回一个正整数:表示当前对象大于被比较的对象。
import java.util.ArrayList;
import java.util.Collections;
// 1. 自定义类,实现 Comparable 接口
class Student implements Comparable<Student> {
    private String name;
    private int age;
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    // 2. 重写 compareTo 方法,定义“自然排序”规则(这里按年龄升序)
    @Override
    public int compareTo(Student other) {
        // this < other -> return negative
        // this == other -> return 0
        // this > other -> return positive
        return this.age - other.age;
    }
    // 为了方便打印,重写 toString 方法
    @Override
    public String toString() {
        return "Student{name='" + name + "', age=" + age + "}";
    }
}
public class SortCustomObjectExample {
    public static void main(String[] args) {
        ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 22));
        students.add(new Student("Bob", 20));
        students.add(new Student("Charlie", 25));
        students.add(new Student("David", 20));
        System.out.println("排序前的 ArrayList: " + students);
        // 3. 使用 Collections.sort() 进行排序
        Collections.sort(students);
        System.out.println("按年龄升序排序后的 ArrayList: " + students);
    }
}

输出:

排序前的 ArrayList: [Student{name='Alice', age=22}, Student{name='Bob', age=20}, Student{name='Charlie', age=25}, Student{name='David', age=20}]
按年龄升序排序后的 ArrayList: [Student{name='Bob', age=20}, Student{name='David', age=20}, Student{name='Alice', age=22}, Student{name='Charlie', age=25}]

可以看到,Bob 和 David 年龄相同,它们的相对位置保持了稳定(这是 List.sort() 的一个特性,当比较结果为0时,不交换位置)。

Java ArrayList如何排序?-图3
(图片来源网络,侵删)

自定义排序规则

当你需要按照不同的规则进行排序时(对 Student 按姓名排序,或者按年龄降序排序),可以使用 Comparator 接口,你可以通过以下两种方式创建 Comparator

实现 Comparator 接口(传统方式)

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
// Student 类同上...
public class SortWithComparatorExample {
    public static void main(String[] args) {
        ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 22));
        students.add(new Student("Bob", 20));
        students.add(new Student("Charlie", 25));
        students.add(new Student("David", 20));
        System.out.println("排序前的 ArrayList: " + students);
        // 1. 创建一个按姓名排序的 Comparator
        Comparator<Student> nameComparator = new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                return s1.getName().compareTo(s2.getName());
            }
        };
        // 2. 使用 Collections.sort() 并传入 Comparator
        Collections.sort(students, nameComparator);
        System.out.println("按姓名升序排序后的 ArrayList: " + students);
        // 3. 创建一个按年龄降序排序的 Comparator
        Comparator<Student> ageDescComparator = new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                // s2.age - s1.age 实现降序
                return s2.getAge() - s1.getAge();
            }
        };
        Collections.sort(students, ageDescComparator);
        System.out.println("按年龄降序排序后的 ArrayList: " + students);
    }
}

使用 Lambda 表达式(Java 8+ 推荐)

这是更简洁、更现代的方式。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
// Student 类同上...
public class SortWithLambdaExample {
    public static void main(String[] args) {
        ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 22));
        students.add(new Student("Bob", 20));
        students.add(new Student("Charlie", 25));
        students.add(new Student("David", 20));
        System.out.println("排序前的 ArrayList: " + students);
        // 1. 使用 Lambda 表达式按姓名升序排序
        Collections.sort(students, (s1, s2) -> s1.getName().compareTo(s2.getName()));
        System.out.println("按姓名升序排序后的 ArrayList: " + students);
        // 2. 使用 Lambda 表达式按年龄降序排序
        Collections.sort(students, (s1, s2) -> s2.getAge() - s1.getAge());
        System.out.println("按年龄降序排序后的 ArrayList: " + students);
    }
}

使用 List.sort() 方法(Java 8+)

从 Java 8 开始,List 接口本身增加了 sort(Comparator<? super E> c) 方法,功能和 Collections.sort(list, c) 一样,但更面向对象。

import java.util.ArrayList;
import java.util.Comparator;
// Student 类同上...
public class ListSortMethodExample {
    public static void main(String[] args) {
        ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 22));
        students.add(new Student("Bob", 20));
        students.add(new Student("Charlie", 25));
        students.add(new Student("David", 20));
        System.out.println("排序前的 ArrayList: " + students);
        // 使用 List.sort() 和 Lambda 表达式
        students.sort((s1, s2) -> s1.getName().compareTo(s2.getName()));
        System.out.println("按姓名升序排序后的 ArrayList: " + students);
        students.sort((s1, s2) -> Integer.compare(s2.getAge(), s1.getAge())); // 使用 Integer.compare 更安全
        System.out.println("按年龄降序排序后的 ArrayList: " + students);
    }
}

注意:当比较 int 等基本类型时,直接相减可能会导致整数溢出。Integer.MIN_VALUE - Integer.MAX_VALUE 会溢出,使用 Integer.compare(a, b)Double.compare(a, b) 是更安全的选择。


并行排序

对于非常大的 ArrayList,可以利用多核 CPU 的优势进行并行排序,以提高性能。

示例:使用 List.parallelSort()

Java 8 引入了 parallelSort() 方法。

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ParallelSortExample {
    public static void main(String[] args) {
        // 创建一个包含大量数据的 ArrayList
        ArrayList<Integer> largeList = new ArrayList<>();
        Random random = new Random();
        for (int i = 0; i < 10_000_000; i++) {
            largeList.add(random.nextInt());
        }
        System.out.println("列表大小: " + largeList.size());
        // 复制一份用于比较
        ArrayList<Integer> listForSequentialSort = new ArrayList<>(largeList);
        ArrayList<Integer> listForParallelSort = new ArrayList<>(largeList);
        // --- 顺序排序 ---
        long startTime = System.currentTimeMillis();
        Collections.sort(listForSequentialSort);
        long endTime = System.currentTimeMillis();
        System.out.println("顺序排序耗时: " + (endTime - startTime) + " 毫秒");
        // --- 并行排序 ---
        startTime = System.currentTimeMillis();
        listForParallelSort.parallelSort(); // 注意:List.parallelSort() 需要 List 是 ArrayList 或 RandomAccess 子类
        endTime = System.currentTimeMillis();
        System.out.println("并行排序耗时: " + (endTime - startTime) + " 毫秒");
    }
}

注意:并行排序在数据量较小或者 CPU 核心数不多时,可能因为线程调度的开销而比顺序排序慢,它适用于数据量非常大的场景。


总结与对比

方法 适用场景 特点
Collections.sort(list) 对实现了 Comparable 的对象进行自然排序 简单直接,但排序规则在类内部定义,不够灵活。
Collections.sort(list, comparator) 需要自定义排序规则时。 灵活,可以在任何地方定义排序逻辑。
list.sort(comparator) Java 8+,需要自定义排序规则时。 更面向对象,是 List 接口的方法,语义更清晰。推荐使用
list.parallelSort() 非常大的列表进行排序,以利用多核CPU。 性能高,但有小数据量下性能可能更差的风险。

推荐实践:

  1. 如果你的类有明确的“自然顺序”(如 String 按字典序,Number 按数值大小),并且总是按这个顺序排序,就让类实现 Comparable 接口。
  2. 如果你需要根据不同场景、不同属性进行排序,或者排序规则可能变化,请使用 Comparator
  3. 在 Java 8 及以上版本,优先使用 list.sort(comparator) 和 Lambda 表达式,因为它代码更简洁、可读性更高。
分享:
扫描分享到社交APP
上一篇
下一篇