java - 无法将数组和比较器作为泛型类型传递

标签 java generics comparator

我对泛型类型有点缺乏了解,希望得到一些澄清。在我的Java教材中,为我们提供了一个归并排序的程序:

import java.util.Comparator;

public class mergeSortBook{
    public static<K>void merge(K[] S1,K[] S2,K[] S,Comparator<K>comp){
        int i=0,j=0;
        while(i+j<S.length) {
            if(j==S2.length || (i<S1.length && comp.compare(S1[i],S2[j])<0))
                S[i+j]=S1[i++];
            else 
                S[i+j]=S2[j++];
        }
    }
    public static<K>void mergeSort(K[] S,Comparator<K>comp){
        int n=S.length;
        if (n<2) return;
        int mid = n/2;
        K[] S1 = Arrays.copyOfRange(S, 0, mid);
        K[] S2 = Arrays.copyOfRange(S, mid, n);
        mergeSort(S1,comp);
        mergeSort(S2,comp);
        merge(S1,S2,S,comp);
    }
}

我正在尝试实现上述算法。经过一番研究,我决定实例化一个默认比较器并将其传递给 mergeSort() 函数。但是,我在尝试传递数组时遇到了问题。我的 Eclipse IDE 中的错误是 The method mergeSort(K[], Comparator<K>) in the type mergeSortBook is not applicable for the arguments (int[],mergeSortBook.DefaultComparator<Integer>)

下面是我的 main 方法和 DefaultComparator 方法的代码。我真的很感激任何关于传递正确类型的参数以使程序运行的提示。

    public class DefaultComparator<E> implements Comparator<E> 
    {
        @Override
        public int compare(E a, E b) throws ClassCastException {
            return ((Comparable<E>) a).compareTo(b);
        }
    }
    public static void main(String args[]) {

        int arr[] = {3,1,6,2,4,8,9,2,1};
        mergeSort(arr,new DefaultComparator<Integer>());
    }

最佳答案

您需要一个Integer使用泛型方法( int 是原始类型,而不是 Comparable )。您还可以使用 Comparator.naturalOrder() 。就像,

public static void main(String args[]) {
    Integer[] arr = { 3, 1, 6, 2, 4, 8, 9, 2, 1 };
    mergeSort(arr, Comparator.naturalOrder());
    System.out.println(Arrays.toString(arr));
}

输出

[1, 1, 2, 2, 3, 4, 6, 8, 9]

最后,代替 Comparator<K> “正确”的类型是 Comparator<? super K> 。并且不要仅仅因为它是合法的就省略大括号。和S1 , S2S不是特别有意义(或有帮助)的变量名称。它们不像类型那样遵循 Java 命名约定。我们可以做得更好,仍然使用简称。就像,

public static <K> void merge(K[] left, K[] right, K[] arr, Comparator<? super K> comp) {
    int i = 0, j = 0;
    while (i + j < arr.length) {
        if (j == right.length || (i<left.length && comp.compare(left[i], right[j])<0)) {
            arr[i + j] = left[i++];
        } else {
            arr[i + j] = right[j++];
        }
    }
}

如果您要将声明放在一行上,保持一致。就像,

public static <K> void mergeSort(K[] arr, Comparator<? super K> comp) {
    int n = arr.length, mid = n / 2;
    if (n < 2) {
        return;
    }
    K[] left = Arrays.copyOfRange(arr, 0, mid), right = Arrays.copyOfRange(arr, mid, n);
    mergeSort(left, comp);
    mergeSort(right, comp);
    merge(left, right, arr, comp);
}

关于java - 无法将数组和比较器作为泛型类型传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49330415/

相关文章:

javascript - Typescript:类型 '{}' 无法分配给类型 'Pick<T, K>' ,如何正确键入 javascript `pick` 函数?

java - 按属性对自定义对象的 ArrayList 进行排序

java.util.Comparator.naturalOrder 采用 <T extends Comparable<? super T>> 并返回一个 Comparator<T> - 为什么?

java - 短到十六进制字符串

scala - 如何将类型限制为 Scala 中的特定类型

C#(泛型的泛型)?

java - 如何按日期字段对集合进行排序?

java - 根据按下的按钮显示信息

java - 检查main的退出状态

java - 创建一个简单的 "shopping cart"程序