杰瑞科技汇

Java List如何自定义排序规则?

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

这是最现代、最简洁的方法,直接在 List 对象上进行排序,会原地修改(in-place sort)列表本身。

Java List如何自定义排序规则?-图1
(图片来源网络,侵删)

核心思想: List.sort() 方法接受一个 Comparator 对象,用来定义排序的规则。

自然排序 (按字母/字典序)

这是最常见的排序方式,按照字符串的 Unicode 码点(对于英文来说就是字典序)进行排序。

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class SortListExample {
    public static void main(String[] args) {
        List<String> fruits = new ArrayList<>();
        fruits.add("Banana");
        fruits.add("Apple");
        fruits.add("Orange");
        fruits.add("Grape");
        fruits.add("cherry"); // 注意小写字母
        System.out.println("排序前: " + fruits);
        // 使用 String 类自带的自然顺序比较器
        fruits.sort(Comparator.naturalOrder());
        System.out.println("自然排序后: " + fruits);
    }
}

输出:

排序前: [Banana, Apple, Orange, Grape, cherry]
自然排序后: [Apple, Banana, Grape, Orange, cherry]

注意: 在 Java 中,大写字母的 Unicode 码点比小写字母小,"Apple" 会排在 "cherry" 前面,如果你希望不区分大小写排序,请看下面的方法。

Java List如何自定义排序规则?-图2
(图片来源网络,侵删)

自定义排序 (不区分大小写)

使用 String.CASE_INSENSITIVE_ORDER 比较器可以实现不区分大小写的字典序排序。

import java.util.ArrayList;
import java.util.List;
public class SortListCaseInsensitive {
    public static void main(String[] args) {
        List<String> fruits = new ArrayList<>();
        fruits.add("Banana");
        fruits.add("Apple");
        fruits.add("orange");
        fruits.add("Grape");
        fruits.add("cherry");
        System.out.println("排序前: " + fruits);
        // 使用不区分大小写的比较器
        fruits.sort(String.CASE_INSENSITIVE_ORDER);
        System.out.println("不区分大小写排序后: " + fruits);
    }
}

输出:

排序前: [Banana, Apple, orange, Grape, cherry]
不区分大小写排序后: [Apple, Banana, cherry, Grape, orange]

降序排序

Comparator 提供了 reversed() 方法,可以轻松地将任何比较器反转。

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class SortListDescending {
    public static void main(String[] args) {
        List<String> fruits = new ArrayList<>();
        fruits.add("Banana");
        fruits.add("Apple");
        fruits.add("Orange");
        System.out.println("排序前: " + fruits);
        // 先自然排序,然后反转
        fruits.sort(Comparator.naturalOrder().reversed());
        System.out.println("降序排序后: " + fruits);
    }
}

输出:

Java List如何自定义排序规则?-图3
(图片来源网络,侵删)
排序前: [Banana, Apple, Orange]
降序排序后: [Orange, Banana, Apple]

使用 Collections.sort() 方法 (传统方法)

在 Java 8 之前,这是对 List 进行排序的标准方法,它的作用和 List.sort() 一样,也是原地修改列表。

核心思想: Collections.sort() 是一个静态工具方法,它接收一个 List 和一个可选的 Comparator

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CollectionsSortExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("David");
        names.add("Charlie");
        names.add("Alice");
        names.add("Bob");
        System.out.println("排序前: " + names);
        // 使用 Collections.sort() 进行自然排序
        Collections.sort(names);
        System.out.println("自然排序后: " + names);
        // 降序排序
        Collections.sort(names, Comparator.reverseOrder());
        System.out.println("降序排序后: " + names);
    }
}

输出:

排序前: [David, Charlie, Alice, Bob]
自然排序后: [Alice, Bob, Charlie, David]
降序排序后: [David, Charlie, Bob, Alice]

注意: Collections.sort() 的第二个参数是一个 Comparator,如果你不提供,它会使用元素的自然顺序(对于 String 来说就是字典序)。


使用 Stream API (Java 8+ 功能强大)

Stream API 提供了非常灵活的方式来处理集合,排序只是其中之一。与前面两种方法不同,Stream 排序会返回一个新的已排序列表,而不会修改原始列表。

核心思想:List 转换为 Stream,使用 sorted() 方法进行排序,然后再收集回一个 List

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class StreamSortExample {
    public static void main(String[] args) {
        List<String> items = new ArrayList<>();
        items.add("Java");
        items.add("Python");
        items.add("C++");
        items.add("JavaScript");
        System.out.println("原始列表: " + items);
        // 1. 自然排序 (返回新列表)
        List<String> sortedList = items.stream()
                                       .sorted()
                                       .collect(Collectors.toList());
        System.out.println("Stream 自然排序后: " + sortedList);
        System.out.println("原始列表未改变: " + items); // 原始列表保持不变
        // 2. 降序排序
        List<String> reverseSortedList = items.stream()
                                              .sorted(Comparator.reverseOrder())
                                              .collect(Collectors.toList());
        System.out.println("Stream 降序排序后: " + reverseSortedList);
        // 3. 按字符串长度排序
        List<String> lengthSortedList = items.stream()
                                            .sorted(Comparator.comparingInt(String::length))
                                            .collect(Collectors.toList());
        System.out.println("按长度排序后: " + lengthSortedList);
        // 4. 按长度排序,如果长度相同则按字典序
        List<String> complexSortedList = items.stream()
                                              .sorted(Comparator.comparingInt(String::length)
                                                                .thenComparing(Comparator.naturalOrder()))
                                              .collect(Collectors.toList());
        System.out.println("按长度和字典序排序后: " + complexSortedList);
    }
}

输出:

原始列表: [Java, Python, C++, JavaScript]
Stream 自然排序后: [C++, Java, JavaScript, Python]
原始列表未改变: [Java, Python, C++, JavaScript]
Stream 降序排序后: [Python, JavaScript, Java, C++]
按长度排序后: [C++, Java, Python, JavaScript]
按长度和字典序排序后: [C++, Java, Python, JavaScript]

自定义复杂排序规则

你可能需要根据更复杂的逻辑来排序,比如字符串中包含的数字,这时,你需要编写一个自定义的 Comparator

场景: 对一个包含文件名的列表进行排序,希望数字部分能按数值大小排序,而不是字典序。 ["file1.txt", "file10.txt", "file2.txt"] -> ["file1.txt", "file2.txt", "file10.txt"]

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CustomSortExample {
    public static void main(String[] args) {
        List<String> files = new ArrayList<>();
        files.add("file10.txt");
        files.add("file1.txt");
        files.add("file2.txt");
        files.add("file_a.txt");
        files.add("file_b.txt");
        System.out.println("排序前: " + files);
        // 定义自定义比较器
        Comparator<String> customComparator = (s1, s2) -> {
            // 使用正则表达式提取字符串中的数字
            Pattern pattern = Pattern.compile("\\d+");
            Matcher matcher1 = pattern.matcher(s1);
            Matcher matcher2 = pattern.matcher(s2);
            // 如果两个字符串都包含数字
            if (matcher1.find() && matcher2.find()) {
                int num1 = Integer.parseInt(matcher1.group());
                int num2 = Integer.parseInt(matcher2.group());
                return Integer.compare(num1, num2);
            }
            // 如果只有一个包含数字,或者都不包含,则按字典序
            return s1.compareTo(s2);
        };
        files.sort(customComparator);
        System.out.println("自定义规则排序后: " + files);
    }
}

输出:


排序前: [file10.txt, file1.txt,
分享:
扫描分享到社交APP
上一篇
下一篇