All of Java's collection classes and interfaces are generics, which means they are intended to be used with type parameters. For historical reasons it's possible to use them without type parameters, which is what you've done here. However, it's a bad idea to do that, because
- you sacrifice a lot of the type safety that the compiler gives you,
- you end up casting objects to whatever type you need them to be, which is prone to error, and such errors usually only reveal themselves at run time.
Finding errors at compile time is better than finding them at run time. The compiler is your friend - it gives you messages to help you find your errors.
Now in this particular case, you seem to be building a sorted list of values from your map. But it only makes sense to do this if the values in your map belong to some type that can be sorted. There's no general way of sorting Object
, so for this to make sense, you want to restrict your parameter to be a map whose values can be sorted, or to put it another way, can be compared to other objects of the same type.
The generic interface that tells you that one object can be compared to another is Comparable
. So if you have a type V
, then writing V extends Comparable<V>
means that one object of type V
can be compared to other objects of type V
, using the compareTo
method. This is the condition that you want the type of the values in your map to obey. You don't need any such condition on the type of the keys in your map.
Therefore, you could write your method as generic, which means that its signature will list some type parameters, inside < >
characters, possibly with some conditions on those type parameters. In your case, you'd give your method a signature like this, assuming it's going to return a List
.
private static <K, V extends Comparable<V>> List<V> sortAndListValues(Map<K,V> map)
Of course, if you really intend to return some kind of sorted map, then it might be more like
private static <K, V extends Comparable<V>> Map<K,V> sortByValues(Map<K,V> map)
but you need to remember that it's not possible to sort HashMap
objects. They're naturally sorted in an order that's implied by the hashCode
function of the key class, and by the current size of the map. This is generally not a very useful order. There are other types of map in the JDK, such as
TreeMap
, which sorts its entries according to the key - not what you want here
LinkedHashMap
, which sorts its entries according to the order they were inserted - and you could probably make use of this here.
For the sake of answering your question though, I'm just going to write the List
version of your method.
private static <K, V extends Comparable<V>> List<V> sortAndListValues(Map<K,V> map) {
List<V> toReturn = new LinkedList<>(map.values());
Collections.sort(toReturn, new Comparator<V>() {
public int compare(V first, V second) {
return first.compareTo(second);
}
});
return toReturn;
}
Note that by using the type parameters K
and V
wherever it's appropriate to do so, there's no need for any kind of casting. The compiler will also warn you if you try to use any of the objects in the map in a way that's inappropriate for their type.
There are shorter ways of writing this of course, using the "functional style" that comes with Java 8. But that's a topic for another post entirely.