0
public class Solution {

  public static void main(String[] args) {

    HashMap<String,Integer> hm = new HashMap<>();

    hm.put("red",23);
    hm.put("orange",1);
    hm.put("yellow",32);
    hm.put("green",23);

    TreeMap<String,Integer> tm = new TreeMap<>(new ValueComparator(hm));
    tm.putAll(hm);

    for(String key : tm.keySet())
        System.out.println(key+"  "+tm.get(key));

  }
}

class ValueComparator implements Comparator<String>{

  Map<String, Integer> map;

  public ValueComparator(Map<String, Integer> map){
    this.map =map;
  }

  public int compare(String a, String b){
    return map.get(b).compareTo(map.get(a));
  }

}

Problem: Its correctly sorting based on values but is removing duplicate values. Can please someone point out the reason for that.

Current Output:

yellow 32 
red  23 
orange  1 

Expected Output:

yellow 32 
red  23 
green  23
orange  1 

I have used Comparator inside TreeMap, which in turns sorting HashMap based on values

Vladimir Vagaytsev
  • 2,871
  • 9
  • 33
  • 36
Akash
  • 71
  • 1
  • 11

3 Answers3

2

The Comparator of a TreeMap is meant to compare keys. Your workaround here basically tells the map that "red" and "green" are the same key, and thus it dropped one of them.

You can look here for how to sort a map by values.

Community
  • 1
  • 1
johnnyaug
  • 887
  • 8
  • 24
2

Found a Solution if it help others,

To avoid the keys getting dropped, in the compare method, check if both the values are equal i.e. compare method is returning zero, if yes sort on the keys and return,

public int compare(String a, String b){
    int compare = map.get(a).compareTo(map.get(b));
    if (compare == 0) {
        compare = a.compareTo(b);
    }
    return compare;
}
Akash
  • 71
  • 1
  • 11
  • Thanks for this. I was having the exact same issue. An interesting and unexpected side note I didn't realize about compare that I discovered with some debugging output - It compares the same Key Value pair often. I was sorting a list of three values and the compare function was called five times. Three of those five times were comparing the exact same key and value pair for object a & b. This is most certainly a result of the underlying sort method used. It also explains why a return of 0 doesn't add the key,value pair to the final set. Neat! – Zizzyzizzy Dec 29 '19 at 19:47
0

You can solve this problem by explicitly returning the values in the compare function yourself. For example, here you can modify the compare function in the following way :

public int compare(String a, String b) {

    if (map.get(b).compareTo(map.get(a)) >= 0) {
         return 1;
    }  else {
         return -1;
    }
}

The treeMap comparator does not understand the value 0. So, you can just return 1 or -1 in case the values are same.