java – TreeMap sort by value
Table of Contents
java – TreeMap sort by value
You cant have the TreeMap
itself sort on the values, since that defies the SortedMap
specification:
A
Map
that further provides a total ordering on its keys.
However, using an external collection, you can always sort Map.entrySet()
however you wish, either by keys, values, or even a combination(!!) of the two.
Heres a generic method that returns a SortedSet
of Map.Entry
, given a Map
whose values are Comparable
:
static <K,V extends Comparable<? super V>>
SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map) {
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>() {
@Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
int res = e1.getValue().compareTo(e2.getValue());
return res != 0 ? res : 1;
}
}
);
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
Now you can do the following:
Map<String,Integer> map = new TreeMap<String,Integer>();
map.put(A, 3);
map.put(B, 2);
map.put(C, 1);
System.out.println(map);
// prints {A=3, B=2, C=1}
System.out.println(entriesSortedByValues(map));
// prints [C=1, B=2, A=3]
Note that funky stuff will happen if you try to modify either the SortedSet
itself, or the Map.Entry
within, because this is no longer a view of the original map like entrySet()
is.
Generally speaking, the need to sort a maps entries by its values is atypical.
Note on ==
for Integer
Your original comparator compares Integer
using ==
. This is almost always wrong, since ==
with Integer
operands is a reference equality, not value equality.
System.out.println(new Integer(0) == new Integer(0)); // prints false!!!
Related questions
- When comparing two Integers in Java does auto-unboxing occur? (NO!!!)
- Is it guaranteed that
new Integer(i) == i
in Java? (YES!!!)
polygenelubricants answer is almost perfect. It has one important bug though. It will not handle map entries where the values are the same.
This code:…
Map<String, Integer> nonSortedMap = new HashMap<String, Integer>();
nonSortedMap.put(ape, 1);
nonSortedMap.put(pig, 3);
nonSortedMap.put(cow, 1);
nonSortedMap.put(frog, 2);
for (Entry<String, Integer> entry : entriesSortedByValues(nonSortedMap)) {
System.out.println(entry.getKey()+:+entry.getValue());
}
Would output:
ape:1
frog:2
pig:3
Note how our cow dissapeared as it shared the value 1 with our ape :O!
This modification of the code solves that issue:
static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map) {
SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
new Comparator<Map.Entry<K,V>>() {
@Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
int res = e1.getValue().compareTo(e2.getValue());
return res != 0 ? res : 1; // Special fix to preserve items with equal values
}
}
);
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
java – TreeMap sort by value
In Java 8:
LinkedHashMap<Integer, String> sortedMap = map.entrySet().stream()
.sorted(Map.Entry.comparingByValue(/* Optional: Comparator.reverseOrder() */))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));