TreeMap sort by value
java
Solution
You can't 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.
Here's 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 map's 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!!!)
Problem
I want to write a comparator that will let me sort a TreeMap by value instead of the default natural ordering. I tried something like this, but can't find out what went wrong: ``` import java.util.*; class treeMap { public static void main(String[] args) { System.out.println("the main"); byValue cmp = new byValue(); Map<String, Integer> map = new TreeMap<String, Integer>(cmp); map.put("de",10); map.put("ab", 20); map.put("a",5); for (Map.Entry<String,Integer> pair: map.entrySet()) { System.out.println(pair.getKey()+":"+pair.getValue()); } } } class byValue implements Comparator<Map.Entry<String,Integer>> { public int compare(Map.Entry<String,Integer> e1, Map.Entry<String,Integer> e2) { if (e1.getValue() < e2.getValue()){ return 1; } else if (e1.getValue() == e2.getValue()) { return 0; } else { return -1; } } } ``` I guess what am I asking is: Can I get a `Map.Entry` passed to the comparator?