【发布时间】:2021-07-16 10:00:40
【问题描述】:
如果我想对二维数组进行排序。 (只需重新排序行,不要触摸每行内的数据)。
在以下 sn-p 中:所有 3 种情况都使用相同的 Arrays.sort(T[] a, Comparator<? super T> c) 方法签名。案例(a)工作正常。但是,只需在第二个参数中添加一个 if 条件,T 的推断就会改变。我不明白为什么。
// array contains 3 tuples, sort it by the first element, then second element
int[][] array1 = new int[3][2];
array1[0] = new int[]{1,2};
array1[1] = new int[]{2,3};
array1[2] = new int[]{2,4};
// Case (a): compiles good, tuple is inferred as int[]
Arrays.sort(array1, Comparator.comparingInt(tuple -> tuple[0])); // Arrays.sort(T[] a, Comparator<? super T> c) correctly infers that T refers to int[]
// Case (b.1): compile error: incompatible types
// tuple is now inferred as Object, why?
Arrays.sort(array1,
(a1, a2) -> a1[0] == a2[0] ?
Comparator.comparingInt(tuple -> tuple[1]) : Comparator.comparingInt(tuple -> tuple[0]));
// Case (b.2): compile error: incompatible types
Arrays.sort(array1, Comparator.comparingInt(tuple -> tuple[0]).thenComparingInt(tuple -> tuple[1]));
// Case (c): if downcast tuple[0] to ((int[])tuple)[0], then (b) works fine.
更新:
- 在 cmets 的启发下,我很快意识到案例(b.1)实际上是无效的。
(b.1) 中的 lambda 假设返回一个整数,而不是比较器。例如。
Arrays.sort(array1, (a1, a2) -> a1[0] == a2[0] ? 0 : 1); - 在所有其他情况下,我看到
Comparator.<int[]>comparingInt(...)正确强制推理。
【问题讨论】:
-
很可能是因为当您使用三元
condition ? a : b时,a和b的结果必须在它们的类型中对齐。因此,两个Comparator.comparingInt(...)调用都必须排成一行,并且该过程的复杂规则很可能会失败,并决定Object是确保这一点的唯一方法。 -
请注意,如果自动推断失败,您可以手动指定所需的类型。
Comparator.<int[]>comparingInt(...)。看起来很奇怪,但很有效。 -
有趣的是,在没有
thenComparingInt的情况下,Arrays.sort(array1, Comparator.comparingInt(tuple -> tuple[0]))是如何工作的。 -
无论如何,如果你想要一个字典顺序,你可以做
Arrays.sort(array1, Arrays::compare);。不需要所有这些thenComparing的东西。 -
Arrays::compare的通用 Java 8 替代方案是Comparator.comparing(IntBuffer::wrap)。但是当已知数组总是有两个元素时,我会保留Comparator.comparingInt((int[] a)->a[0]).thenComparingInt(a->a[1])。
标签: java arrays java-8 comparator