37

I need a comparator for a TreeMap. Should I write this anonymously in the constructor for my TreeMap? How else could I write my comparator. Currently, Java does not like my code (can I do this anonymously?):

SortedMap<String, Double> myMap = 
    new TreeMap<String, Double>(new Comparator<Entry<String, Double>>()
    {
        public int compare(Entry<String, Double> o1, Entry<String, Double> o2)
        {
            return o1.getValue().compareTo(o2.getValue());
        } 
    });
  1. Can I do the above anonymously?
  2. How else could I do this?
  3. I want to sort myMap by the Value not the Key
CodeKingPlusPlus
  • 15,383
  • 51
  • 135
  • 216
  • The TreeMap comparator signature is on the key only. For example: ``` new Comparator() { @Override public int compare(String a, String b) { return 0; } ``` – figaro Jul 01 '21 at 17:08

3 Answers3

73

You can not sort TreeMap on values.

A Red-Black tree based NavigableMap implementation. The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used You will need to provide comparator for Comparator<? super K> so your comparator should compare on keys.

To provide sort on values you will need SortedSet. Use

SortedSet<Map.Entry<String, Double>> sortedset = new TreeSet<Map.Entry<String, Double>>(
            new Comparator<Map.Entry<String, Double>>() {
                @Override
                public int compare(Map.Entry<String, Double> e1,
                        Map.Entry<String, Double> e2) {
                    return e1.getValue().compareTo(e2.getValue());
                }
            });

  sortedset.addAll(myMap.entrySet());

To give you an example

    SortedMap<String, Double> myMap = new TreeMap<String, Double>();
    myMap.put("a", 10.0);
    myMap.put("b", 9.0);
    myMap.put("c", 11.0);
    myMap.put("d", 2.0);
    sortedset.addAll(myMap.entrySet());
    System.out.println(sortedset);

Output:

  [d=2.0, b=9.0, a=10.0, c=11.0]
Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72
  • How do I add an element one at a time to myMap? myMap.add(Map.Entry new Map.Entry(vStr, cur)); – CodeKingPlusPlus Oct 18 '12 at 04:52
  • @CodeKingPlusPlus No. you use put method only Check the example that is added. You put values to Map once your are done use SortedSet to sort values. – Amit Deshpande Oct 18 '12 at 04:56
  • 1
    This works but it removes duplicate values. But i want to keep duplicate values in the list. Can anyone help me? – Priyanka Alachiya Aug 14 '20 at 11:03
  • ..or "even you take elements and order them, when you put them back into a TreeMap, the order is still decided by the **key** comparator/natural order". Instead, you can insert the ordered entries into a `LinkedHashmap` to at least return an ordered map view of elements. – WesternGun Oct 20 '20 at 19:30
  • 1
    @PriyankaAlachiya Use an ArrayList instead of a set. Add the elements of the map to the list and pass in the comparator in Collections.sort(). Worked for me. Also I used technique when solving "Top K Frequent Elements" on leetcode – cs-dev Oct 28 '20 at 14:19
18

The comparator should be only for the key, not for the whole entry. It sorts the entries based on the keys.

You should change it to something as follows

SortedMap<String, Double> myMap = 
    new TreeMap<String, Double>(new Comparator<String>()
    {
        public int compare(String o1, String o2)
        {
            return o1.compareTo(o2);
        } 
});

Update

You can do something as follows (create a list of entries in the map and sort the list base on value, but note this not going to sort the map itself) -

List<Map.Entry<String, Double>> entryList = new ArrayList<Map.Entry<String, Double>>(myMap.entrySet());
    Collections.sort(entryList, new Comparator<Map.Entry<String, Double>>() {
        @Override
        public int compare(Entry<String, Double> o1, Entry<String, Double> o2) {
            return o1.getValue().compareTo(o2.getValue());
        }
    });
Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
  • @CodeKingPlusPlus: You cannot sort the map itself based on values. But you can get list of entries and sort it. But then it might not make sense to have a TreeMap, unless you switch the key and value. – Bhesh Gurung Oct 18 '12 at 04:31
0

you can swipe the key and the value. For example

        String[] k = {"Elena", "Thomas", "Hamilton", "Suzie", "Phil"};
        int[] v = {341, 273, 278, 329, 445};
        TreeMap<Integer,String>a=new TreeMap();
        for (int i = 0; i < k.length; i++) 
           a.put(v[i],k[i]);            
        System.out.println(a.firstEntry().getValue()+"\t"+a.firstEntry().getKey());
        a.remove(a.firstEntry().getKey());
        System.out.println(a.firstEntry().getValue()+"\t"+a.firstEntry().getKey());