我想实现合并排序,但在这种情况下我需要保护的最大值。我累了使用null作为最大值,但我得到空指针异常。
private static <T extends Comparable<? super T>> void merge(T[] A, int p, int q, int r) {
T[] L = Arrays.copyOfRange(A, p, q + 1);
T[] R = Arrays.copyOfRange(A, q, r + 1);
L[L.length - 1] = null; //guard
R[R.length - 1] = null; //guard
int i = 0;
int j = 0;
// i+j < r - k
for (int k = p; k < r; k++) {
if (L[i].compareTo(R[j]) <= 0) {
A[k] = L[i];
i++;
}
else {
A[k] = R[j];
j++;
}
}
}
所以我定义了
Comparable<T> guard = new Comparable<T>(){
@Override
public int compareTo(T o) {
return 1; //always max
}};
L[L.length - 1] = (T) guard;
R[R.length - 1] = (T) guard;
但如果我将它用作guard而不是null,我可以重写代码,但我总是得到ArrayStoreException
如何以正确的方式做?
所以问题是: 如何在不知道什么是T的情况下定义与T类型具有可比性的对象。
答案 0 :(得分:0)
如果要排序正值或非常大的值
,则不能使用null,而是使用-1而不是
L[L.length - 1] = null; //guard
R[R.length - 1] = null; //guard
使用
L[L.length - 1] = -1; //guard
R[R.length - 1] = -1; //guard
答案 1 :(得分:0)
定义总是返回1的比较器是个坏主意,它不能确认比较器的要求。
你总是知道守卫在哪里,所以你可以检查索引,或者你可以检查是否为空。所以只需添加特殊逻辑,如果元素是一个保护,它将绕过比较器 像这样:
for (int k = p; k < r; k++) {
if (R[j] == null || (L[i] != null && L[i].compareTo(R[j]) <= 0)) {
A[k] = L[i];
i++;
}
else {
A[k] = R[j];
j++;
}
}