Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the easiest way to sort maps according to values in Java?

I want my hash to sort in descending order according to the values. How do I do that in Java?

like image 378
unj2 Avatar asked Dec 12 '09 17:12

unj2


People also ask

How sort a Map based on its values in Java?

In Java, sorting HashMap by values is complicated because there is no direct method available. If we need to sort the HashMap by values, we should create a Comparator. It compares two elements based on the values. After that get the Set of elements from the Map and convert Set into the List.

Can maps be sorted in Java?

Java HashMap does not preserve any order by default. If there is a need to sort HashMap we sort it explicitly based on the requirements. Java provides an option to sort HashMap based on keys and values. In this section, we will learn how to sort HashMap according to keys and values.

Is Map sorted by value or key?

A map is not meant to be sorted, but accessed fast. Object equal values break the constraint of the map.


1 Answers

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.
    }
});
like image 121
BalusC Avatar answered Nov 14 '22 21:11

BalusC