用于在 Java 中对二维数组和一维数组进行排序的比较器
Comparator for sorting 2D arrays and 1D arrays in Java
我使用以下代码对 int[][] 类型的二维数组进行排序 逆序 通过使用比较器。
int[][] arr = {{2,3},{3,5},{5,8}};
Arrays.sort(arr, (a,b) -> Integer.compare(b[1], a[1]));
但是我无法使用类似的方法对 int[] 类型的一维数组进行排序。在互联网上我发现信息说“按降序对原始数组进行排序的唯一方法是,先按升序对数组进行排序,然后再原地反转数组。”
为什么我可以对基本类型的二维数组进行排序,但不能使用比较器对一维数组进行排序?
只是没有任何 built-in 接受一维原始数组和 Comparator
的排序方法。
至于为什么,只有设计者可以权威地说,这里有一些反对意见:
- 最初在 Java 程序中并不经常使用原始数组。
- 使用
Comparator
的 sort
实现需要将每个数组元素包装在一个对象中以将它们传递给 Comparator
,因此您不妨让用户转换将 int
的数组转换为 Integer
本身的数组。
- 您需要再添加 7 或 14 个
Arrays.sort
implementations,这是一个 non-trivial 的代码量来测试
- 自定义比较器最常见的用例是反向排序,您已经可以通过先排序然后反向来实现
可以按降序对 int[][]
进行排序,因为基本上是将 int[]
相互比较。根据 JLS, §10:“...数组是对象...”。
仔细观察 Arrays
API, we find method sort(T[], Comparator<? super T>)
, which, together with some static builder methods from Comparator
,允许 reverse-sort 对象数组:
T[] someArray = ...
Arrays.sort(someArray, Comparator.<T>naturalOrder().reversed())
这仅适用于 object-arrays,不适用于原始数组。对于原始数组,我们在 Arrays
中没有任何方法 sort(int[], Comparator<...>)
(可能是因为不能将原始数组用作泛型类型,project Valhalla 将来可能会或可能不会更改)。
所以是的,如果想要拥有恒定的内存开销,那么对基元数组进行排序然后将其反转似乎是唯一的选择。它看起来像这样(草图):
final int[] values = { 1, 5, 3, 2, 4 };
Arrays.sort(values);
reverse(values);
您可以使用 Stream
将 int
转换为 Integer
,使用 Comparator
进行排序并将其重新转换为 int[]
。
final int[] values = {2, 0, 5, 1, 3, 4};
int[] reversed = IntStream.of(values)
.boxed()
.sorted(Comparator.reverseOrder())
.mapToInt(i -> i)
.toArray();
System.out.println(Arrays.toString(reversed));
输出:
[5, 4, 3, 2, 1, 0]
我使用以下代码对 int[][] 类型的二维数组进行排序 逆序 通过使用比较器。
int[][] arr = {{2,3},{3,5},{5,8}};
Arrays.sort(arr, (a,b) -> Integer.compare(b[1], a[1]));
但是我无法使用类似的方法对 int[] 类型的一维数组进行排序。在互联网上我发现信息说“按降序对原始数组进行排序的唯一方法是,先按升序对数组进行排序,然后再原地反转数组。”
为什么我可以对基本类型的二维数组进行排序,但不能使用比较器对一维数组进行排序?
只是没有任何 built-in 接受一维原始数组和 Comparator
的排序方法。
至于为什么,只有设计者可以权威地说,这里有一些反对意见:
- 最初在 Java 程序中并不经常使用原始数组。
- 使用
Comparator
的sort
实现需要将每个数组元素包装在一个对象中以将它们传递给Comparator
,因此您不妨让用户转换将int
的数组转换为Integer
本身的数组。 - 您需要再添加 7 或 14 个
Arrays.sort
implementations,这是一个 non-trivial 的代码量来测试 - 自定义比较器最常见的用例是反向排序,您已经可以通过先排序然后反向来实现
可以按降序对 int[][]
进行排序,因为基本上是将 int[]
相互比较。根据 JLS, §10:“...数组是对象...”。
仔细观察 Arrays
API, we find method sort(T[], Comparator<? super T>)
, which, together with some static builder methods from Comparator
,允许 reverse-sort 对象数组:
T[] someArray = ...
Arrays.sort(someArray, Comparator.<T>naturalOrder().reversed())
这仅适用于 object-arrays,不适用于原始数组。对于原始数组,我们在 Arrays
中没有任何方法 sort(int[], Comparator<...>)
(可能是因为不能将原始数组用作泛型类型,project Valhalla 将来可能会或可能不会更改)。
所以是的,如果想要拥有恒定的内存开销,那么对基元数组进行排序然后将其反转似乎是唯一的选择。它看起来像这样(草图):
final int[] values = { 1, 5, 3, 2, 4 };
Arrays.sort(values);
reverse(values);
您可以使用 Stream
将 int
转换为 Integer
,使用 Comparator
进行排序并将其重新转换为 int[]
。
final int[] values = {2, 0, 5, 1, 3, 4};
int[] reversed = IntStream.of(values)
.boxed()
.sorted(Comparator.reverseOrder())
.mapToInt(i -> i)
.toArray();
System.out.println(Arrays.toString(reversed));
输出:
[5, 4, 3, 2, 1, 0]