I want my hash to sort in descending order according to the values. How do I do that in Java?
Here's an easy way to do it. It involves writing your own class that implements Comparator and using it to sort your map by value.
For an extensive list of alternative approaches, some of which don't use comparators, it's worth to check out the answers to this SO question.
A HashMap
(and its legacy predecesor Hashtable
) is by nature unordered. Even if you sort it, it will remain unordered. If you want to maintain insertion order, then use LinkedHashMap
instead. If you want an automatic sort on keys, regardless of insertion order, then use SortedMap
instead.
If you want to sort a Map
on values, then you basically need to put the key/value pairs in another kind of a sortable data structure, e.g. List<Entry<K, V>>
, then sort it using Collections#sort()
with help of a Compatator<Entry<K, V>>
and finally repopulate a LinkedHashMap
with it (not a HashMap
or you will lose the ordering again).
Here's a basic example (leaving obvious runtime exception handling aside):
// Prepare.
Map<String, String> map = new HashMap<String, String>();
map.put("foo", "bar");
map.put("bar", "waa");
map.put("waa", "foo");
System.out.println(map); // My JVM shows {waa=foo, foo=bar, bar=waa}
// Get entries and sort them.
List<Entry<String, String>> entries = new ArrayList<Entry<String, String>>(map.entrySet());
Collections.sort(entries, new Comparator<Entry<String, String>>() {
public int compare(Entry<String, String> e1, Entry<String, String> e2) {
return e1.getValue().compareTo(e2.getValue());
}
});
// Put entries back in an ordered map.
Map<String, String> orderedMap = new LinkedHashMap<String, String>();
for (Entry<String, String> entry : entries) {
orderedMap.put(entry.getKey(), entry.getValue());
}
System.out.println(orderedMap); // {foo=bar, waa=foo, bar=waa}
To sort it descencing, use the following Comparator
. Basically just swap the entries to compare:
Collections.sort(entries, new Comparator<Entry<String, String>>() {
public int compare(Entry<String, String> e1, Entry<String, String> e2) {
return e2.getValue().compareTo(e1.getValue()); // Sorts descending.
}
});
Here is how I do it:
public static <K, V extends Comparable<V>> Map<K, V> sortByValues(final Map<K, V> map) {
Comparator<K> valueComparator = new Comparator<K>() {
public int compare(K k1, K k2) {
int compare = map.get(k2).compareTo(map.get(k1));
if (compare == 0) return 1;
else return compare;
}
};
Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
sortedByValues.putAll(map);
return sortedByValues;
}