Recursive Generics

Is there a way to make this method appropriately general and get rid of warnings?

/** * <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); } }); } 

I tried Function<? extends Comparable<?>, T> Function<? extends Comparable<?>, T> and Function<? extends Comparable<? extends Comparable>, T> Function<? extends Comparable<? extends Comparable>, T> Function<? extends Comparable<? extends Comparable>, T> , but did not compile with an error when compareTo called. For the first:

The compareTo method (capture # 9-of?) In the Comparable type is not applicable for arguments (capture # 10-of? Extends Comparable)

+4
java generics unchecked
Dec 07 '11 at 12:53 on
source share
3 answers

Try the following:

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

you will also need super to enable comparators defined for subtypes. More explanation here: http://docs.oracle.com/javase/tutorial/extra/generics/morefun.html

UPDATE

In addition, looking at your code, I see another bike, there is a good Google Collections library that provides a very convenient Ordering concept for processing it.

So your code will look like this:

 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); 
+5
Dec 07 2018-11-11T00:
source share

This works for me (Eclipse compiler)

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

Like others, you can go ahead and declare U as

 U extends Comparable<? super U> 

This will be useful if you have more method arguments / return values ​​depending on U

+2
Dec 07 2018-11-12T00:
source share

What if you declare two parameters for the function?

 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 ... 

No sane person checked himself with the compiler (you have no interfaces and I'm too hungry to mimic them :)), but give it a chance.

I'm also too embarrassed to speculate on whether it should be C extends Comparable<C> or C extends Comparable<? super C> C extends Comparable<? super C> . I think that the first will work and be more general, although in practice most classes do not implement Comparable, except for themselves.

+1
Dec 07 '11 at 12:59
source share



All Articles