1. 概述
在本教程中,我们将讨论按升序和降序对数组进行排序的常用方法。
我们将研究使用Java的Arrays类排序方法以及实现我们自己的Comparator来对数组的值进行排序。
2. 对象定义
在开始之前,让我们快速定义几个我们将在整个教程中排序的数组。首先,我们将创建一个整数数组和一个字符串数组:
int[] numbers = new int[] { -8, 7, 5, 9, 10, -2, 3 };
String[] strings = new String[] { "learning", "java", "with", "tuyucheng" };
我们还创建一个Employee对象数组,其中每个Employee都有一个id和一个name属性:
Employee john = new Employee(6, "John");
Employee mary = new Employee(3, "Mary");
Employee david = new Employee(4, "David");
Employee[] employees = new Employee[] { john, mary, david };
3. 升序排序
Java的Arrays.sort方法为我们提供了一种快速简单的方法来对实现Comparable接口的原始类型数组或对象数组进行升序排序。
对原始类型进行排序时,Arrays.sort方法使用快速排序的双轴实现。但是,在对对象进行排序时,会使用归并排序的迭代实现。
3.1 原始类型
要按升序对原始数组进行排序,我们将数组传递给sort方法:
Arrays.sort(numbers);
assertArrayEquals(new int[] { -8, -2, 3, 5, 7, 9, 10 }, numbers);
3.2 实现Comparable的对象
对于实现Comparable接口的对象,与我们的原始数组一样,我们也可以简单地将数组传递给sort方法:
Arrays.sort(strings);
assertArrayEquals(new String[] { "tuyucheng", "java", "learning", "with" }, strings);
3.3 未实现Comparable的对象
对未实现Comparable接口的对象(例如我们的Employees数组)进行排序时,需要我们指定自己的比较器。
我们可以在Java 8中很容易地做到这一点,方法是在我们的Comparator中指定我们想要比较我们的Employee对象的属性:
Arrays.sort(employees, Comparator.comparing(Employee::getName));
assertArrayEquals(new Employee[] { david, john, mary }, employees);
在本例中,我们指定希望按Employee的name属性对其进行排序。
我们还可以通过使用Comparator的thenComparing方法链接比较来根据多个属性对对象进行排序:
Arrays.sort(employees, Comparator.comparing(Employee::getName).thenComparing(Employee::getId));
4. 降序排序
4.1 原始类型
按降序对基本数组进行排序并不像按升序排序那么简单,因为Java不支持对基本类型使用比较器。为了克服这个不足,我们有几个选择。
首先,我们可以按升序对数组进行排序,然后对数组进行就地反转。
其次,可以将我们的数组转换为列表,使用Guava的Lists.reverse()方法,然后将我们的列表转换回数组。
最后,我们可以将数组转换为Stream,然后将其映射回int数组。它有一个很好的优势,那就是作为单行代码并且只使用核心Java:
numbers = IntStream.of(numbers).boxed().sorted(Comparator.reverseOrder()).mapToInt(i -> i).toArray();
assertArrayEquals(new int[] { 10, 9, 7, 5, 3, -2, -8 }, numbers);
这样做的原因是boxed将每个int转换为Integer,它确实实现了Comparator。
4.2 实现Comparable的对象
按降序对实现Comparable接口的对象数组进行排序非常简单,我们需要做的就是传递一个比较器作为sort方法的第二个参数。
在Java 8中,我们可以使用Comparator.reverseOrder()来指示我们希望数组按降序排序:
Arrays.sort(strings, Comparator.reverseOrder());
assertArrayEquals(new String[] { "with", "learning", "java", "tuyucheng" }, strings);
4.3 未实现Comparable的对象
类似于对实现Comparable的对象进行排序,我们可以通过在比较定义的末尾添加reversed()来反转自定义比较器的顺序:
Arrays.sort(employees, Comparator.comparing(Employee::getName).reversed());
assertArrayEquals(new Employee[] { mary, john, david }, employees);
5. 总结
在本文中,我们讨论了如何使用Arrays.sort方法按升序和降序对原始类型数组和对象数组进行排序。
与往常一样,本教程的完整源代码可在GitHub上获得。