2011-12-07 92 views
4

有没有办法使这种方法正确通用,并取消警告?递归泛型

/** 
* <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(); 
* } 
*});</pre> 
* 
* @param list The collection. 
* @param ascending Whether to sort ascending (<code>true</code>) or descending (<code>false</code>). 
* @param valueFunction The function that retrieves the value of an entry. 
*/ 
public static <T> void sortByValue(List<T> list, final boolean ascending, @SuppressWarnings("rawtypes") final Function<? extends Comparable, T> valueFunction) { 
    Collections.sort(list, new Comparator<T>() { 
     @SuppressWarnings({ "unchecked", "rawtypes" }) 
     @Override public int compare(T o1, T o2) { 
      final Comparable v1 = valueFunction.call(o1); 
      final Comparable v2 = valueFunction.call(o2); 
      return v1.compareTo(v2) * (ascending ? 1 : -1); 
     } 
    }); 
} 

我试图Function<? extends Comparable<?>, T>Function<? extends Comparable<? extends Comparable>, T>但既不编译,与调用compareTo错误。对于前者即:(?捕获#10的延伸可比)

方法的compareTo在类型可比(?捕获#9的)不适用于参数

+0

你能还提供了'Function'类? – melihcelik

+1

嗨,我正在看看这个问题,并没有真正到达任何地方。但我的一个意见是,不要否定'compareTo()'的结果,因为如果有人返回'Integer.MIN_VALUE',它将保持为'Integer.MIN_VALUE',并且排序顺序不会是你想要的。相反,当上升为假时,反转该呼叫,例如,从'a.compareTo(b)'到'b.compareTo(a);'。烦我知道... – Grundlefleck

+0

@Grundlefleck谢谢,我实现了。 –

回答

5

试试这个:

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

另外,在看你的代码,我看到另一个自行车,有一个很好的库中的谷歌集合,它提供了非常方便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); 
+0

嗯,你仍然有'Comparable'原始类型......你可能意思是'?超级C',而不是'T'。在这种情况下,'super'是一个好主意,但不是必须的,因为根据'C' –

+0

哦,我已经对它进行了修改。 – kan

+0

+1 Google搜集示例 –

1

什么如果你为这个函数声明了两个参数?

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,除非他们自己。

+0

也许也可以使用'>'为更通用的解决方案 –

+0

@ratchetfreak哈,只是编辑我自己的答案补充说。 :)。重要的问题:“为了更通用的解决方案,”双关意图? – yshavit

2

这对我的作品(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

+0

对我来说,该代码将被编译,但对该方法的调用不会。调用的样子是什么? – Grundlefleck

+1

查看OP的Javadoc ... –