Рекурсивные дженерики - PullRequest
4 голосов
/ 07 декабря 2011

Есть ли способ сделать этот метод должным образом общим и покончить с предупреждениями?

<code>/**
 * <p>Sort a collection by a certain "value" in its entries. This value is retrieved using
 * the given <code>valueFunction</code> which takes an entry as argument and returns
 * its value.</p>
 * 
 * <p>Example:</p>
 * <pre>// sort tiles by number
 *Collects.sortByValue(tileList, true, new Function<Integer,NormalTile>() {
 *  public Integer call(NormalTile t) {
 *      return t.getNumber();
 *  }
 *});
* * @param list Коллекция. * @param ascending Сортировать по возрастанию (true) или по убыванию (false). * @param valueFunction Функция, которая извлекает значение записи. * / public static void sortByValue (список список, окончательное логическое возрастание, @SuppressWarnings ("rawtypes") final Function <? extends Comparable, T> valueFunction) { Collections.sort (список, новый компаратор () { @SuppressWarnings ({"unchecked", "rawtypes"}) @Override public int Compare (T o1, T o2) { окончательный сопоставимый v1 = valueFunction.call (o1); окончательный сопоставимый v2 = valueFunction.call (o2); return v1.compareTo (v2) * (по возрастанию? 1: -1); } }); }

Я пытался Function<? extends Comparable<?>, T> и Function<? extends Comparable<? extends Comparable>, T>, но не скомпилировал, с ошибкой при вызове compareTo. Для первого это:

Метод compareTo (capture # 9-of?) В типе Comparable не применим для аргументов (capture # 10-of? Extends Comparable)

Ответы [ 3 ]

5 голосов
/ 07 декабря 2011

Попробуйте это:

public static <T, C extends Comparable<? super C>> void sortByValue(List<T> list, final boolean ascending, final Function<C, T> valueFunction) {
    Collections.sort(list, new Comparator<T>() {
        @Override public int compare(T o1, T o2) {
            final C v1 = valueFunction.apply(o1);
            final C v2 = valueFunction.apply(o2);
            return v1.compareTo(v2) * (ascending ? 1 : -1);
        }
    });
}

вам также понадобится super для разрешения компараторов, определенных для подтипов. Больше объяснений здесь: http://docs.oracle.com/javase/tutorial/extra/generics/morefun.html

UPDATE

Также, глядя на ваш код, я вижу еще один велосипед, есть хорошая библиотека Google Collections, которая предоставляет очень удобное понятие Ordering для обработки.

Итак, ваш код будет выглядеть так:

Ordering<NormalTile> myOrdering = Ordering.natural()
  .onResultOf(new Function<Integer,NormalTile>() {
  public Integer call(NormalTile t) {
      return t.getNumber();
  }))
  .nullsLast();
...
Collections.sort(list, myOrdering);
//or
newList = myOrdering.sortedCopy(readonlyList);
2 голосов
/ 07 декабря 2011

Это работает для меня (компилятор Eclipse)

public static <T, U extends Comparable<U>> void sortByValue(
  List<T> list, final boolean ascending, final Function<U, T> valueFunction) {

  Collections.sort(list, new Comparator<T>() {
    @Override
    public int compare(T o1, T o2) {
      final U v1 = valueFunction.call(o1);
      final U v2 = valueFunction.call(o2);
      return v1.compareTo(v2) * (ascending ? 1 : -1);
    }
  });
}

Как и другие, вы можете пойти дальше и объявить U как

U extends Comparable<? super U>

Это пригодится, еслиу вас есть больше аргументов метода / возвращаемых значений в зависимости от U

1 голос
/ 07 декабря 2011

Что если вы объявите два параметра для функции?

public static <T,C extends Comparable<C>> void sortByValue(List<T> list,
    final boolean ascending, final Function<C, T> valueFunction) {
...
final C v1 = ...
final C v2  ...

Разве здравый смысл не проверил себя с помощью компилятора (у вас нет ваших интерфейсов, и я слишком голоден, чтобы издеваться над ними :)), но попробуйте.

Я тоже слишком слаб, чтобы рассуждать о том, должно ли это быть C extends Comparable<C> или C extends Comparable<? super C>. Я думаю, что первый будет работать и будет немного более общим, хотя на практике большинство классов не реализуют Comparable, кроме как против самих себя.

...