2009-11-20 5 views
13

Следующая дает мне сообщение об ошибке:Java Generics: compareTo и "capture # 1-of?"

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 и отсортировать этот список. Я неправильно использую дженерики?

+0

Некоторые из этих должны быть , но у меня нет времени в этой связи, чтобы отсортировать это в ответе. Если никто другой, я не вернусь позже. – bmargulies

ответ

20

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(); 

[EDIT] И что же означает <T extends Comparable<? super T>> List<T>? Первая часть определяет тип T со следующими свойствами: он должен реализовать интерфейс Comparable<? super T> (или Comparable<X>, где X также определяется в терминах T).

? super T означает, что тип, который поддерживает Comparable, должен T или один из его супер типов.

Представьте на этот раз следующее наследство: Double extends Integer extends Number. Это неверно на Java, но представьте, что Double - это всего лишь Integer плюс часть доли. В этом случае Comparable, который работает для Number, также работает для Integer и Double, так как оба получены от Number. Таким образом, Comparable<Number> удовлетворит super для T, являющегося Number, Integer или Double.

До тех пор, пока каждый из этих типов поддерживает интерфейс Comparable, они также удовлетворяют первой части декларации. Это означает, что вы можете перейти в Number для T, и полученный код также будет работать, если в списках есть Integer и Double экземпляров. Если вы Integer для T, вы все равно можете использовать Double, но Number невозможен, потому что он не удовлетворяет T extends Comparable (часть super все равно будет работать).

Следующим шагом является понимание того, что выражение между static и List просто объявляет свойства типа T, который используется далее в коде. Таким образом, вам не нужно повторять эту длинную декларацию снова и снова. Это часть поведения метода (например, public), а не часть фактического кода.

+0

Я получаю ошибку, которую 'T не может быть разрешен для типа. –

+0

Я исправил свой ответ. Этот код компилируется.Вы получаете ошибки, когда используете его, удаляете '', но он должен работать. О, и замените 'LinkedList' на' ArrayList'. Это намного быстрее и использует гораздо меньше памяти. –

+0

Можете ли вы точно объяснить, что означает '>' означает? –