为什么Arrays.sort(T[]a,Comparator<?superT>c)将T推断为二维数组的对象?
假设我想对二维数组进行排序。(只需重新排列行,不要触摸每行内的数据)。
在以下代码段中:所有 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.
更新:
- 受到评论的启发,我很快意识到案例(b.1)实际上是无效的。(b.1) 中的 lambda 假设返回一个整数,而不是一个比较器。例如
Arrays.sort(array1, (a1, a2) -> a1[0] == a2[0] ? 0 : 1); - 在所有其他场景中,我看到
Comparator.<int[]>comparingInt(...)强制推理正确。
回答
简短回答:编译器不够聪明,无法通过如此复杂的表达式进行推断。它需要一些帮助来推断类型:
Arrays.sort(array1, Comparator.<int[]>comparingInt(tuple -> tuple[0]).thenComparingInt(tuple -> tuple[1]));
相关 JEP:http : //openjdk.java.net/jeps/101
至于三元表达式的情况,我认为它需要进一步调整,因为您需要int在 lambda 中返回 an而不是 a Comparator:
Arrays.sort(array1,
(a1, a2) -> a1[0] == a2[0] ?
Comparator.<int[]>comparingInt(tuple -> tuple[1]).compare(a1, a2) :
Comparator.<int[]>comparingInt(tuple -> tuple[0]).compare(a1, a2));
- You can also use `Arrays.sort(array1, Comparator.comparingInt((int[] tuple) -> tuple[0]) .thenComparingInt(tuple -> tuple[1]));`
THE END
二维码