13

以下给了我一条错误消息:

public static List<Comparable<?>> merge(Set<List<Comparable<?>>> lists) {
    List<Comparable<?>> result = new LinkedList<Comparable<?>>();
    HashBiMap<List<Comparable<?>>, Integer> location = HashBiMap.create();

    int totalSize;
    for (List<Comparable<?>> l : lists) {
        location.put(l, 0);
        totalSize += l.size();
    }

    boolean first;
    List<Comparable<?>> lowest; //the list with the lowest item to add
    int index;

    while (result.size() < totalSize) {
        first = true;

        for (List<Comparable<?>> l : lists) {
            if (! l.isEmpty()) {
                if (first) {
                    lowest = l;
                }
                else if (l.get(location.get(l)).compareTo(lowest.get(location.get(lowest))) <= 0) { //error here
                    lowest = l;
                }
            }
        }
        index = location.get(lowest);
        result.add(lowest.get(index));
        lowest.remove(index);
    }
    return result;
}

错误是:

The method compareTo(capture#1-of ?) in the type Comparable<capture#1-of ?> is not applicable for the arguments (Comparable<capture#2-of ?>)

这里发生了什么?我做了所有东西的类型,Comparable所以我可以调用.compareTo并排序这个列表。我是否错误地使用了泛型?

4

1 回答 1

21

List<?>表示“任何事物的列表”,因此具有这种类型的两个对象是不同的:一个可能是 的列表String,另一个可能是 的列表BigDecimal。很显然,这些并不相同。

List<T>意思是“任何东西的清单,但当你T再次看到时,它是一样的T”。

当您在不同的地方使用相同的类型时,您必须告诉编译器。尝试:

public static <T extends Comparable<? super T>> List<T> merge(Set<List<T>> lists) {
    List<T> result = new LinkedList<T>();
    HashBiMap<List<T>, Integer> location = HashBiMap.create();

[编辑] 那是什么<T extends Comparable<? super T>> List<T>意思?第一部分定义了T具有以下属性的类型: 它必须实现接口Comparable<? super T>(或者Comparable<X>whereX也根据 定义T)。

? super T表示Comparable支持必须的T类型或其超类型之一。

想象一下这个继承:Double extends Integer extends Number. 这在 Java 中是不正确的,但可以想象这Double只是一个Integer加分数部分。在这种情况下,适用于的 aComparableNumber适用于Integer并且Double因为两者都派生自Number. 所以Comparable<Number>会满足存在的super部分,或。TNumberIntegerDouble

As long as each of these types support the Comparable interface, they also satisfy the first part of the declaration. This means, you can pass in Number for T and the resulting code will also work when there are Integer and Double instances in the lists. If you Integer for T, you can still use Double but Number is not possible because it doesn't satisfy T extends Comparable anymore (the super part would still work, though).

The next step is to understand that the expression between static and List just declares the properties of the type T which is used later in the code. This way, you don't have to repeat this long declaration over and over again. It's part of the behavior of the method (like public) and not part of the actual code.

于 2009-11-20T15:13:39.830 回答