1

How to sort a hash map based on values and if the values are same then the sorting should be on the key.

I tried to use a comparator, but its not giving expected results.

I want the result to be like this

{Bajaj=8.0, Tata=7.99, Maruthi=6.34, Kmart=5.99, Honda=5.78, 
Adidas=4.99, Ford=3.99, Nike=3.99, Sears=3.99, Suzuki=3.99, 
Apple=2.99, Puma=1.99}

Here's the complete source code:

import java.util.*;

public class Test {
    public static void main(String[] args) {

        HashMap<String, Double> map = new HashMap<String, Double>();
        ValueComparator bvc = new ValueComparator(map);
        TreeMap<String, Double> sorted_map = new TreeMap<String, Double>(bvc);

        map.put("Adidas", 4.99);
        map.put("Nike", 3.99);
        map.put("Puma", 1.99);
        map.put("Ford", 3.99);
        map.put("Apple", 2.99);
        map.put("Sears", 3.99);
        map.put("Kmart", 5.99);
        map.put("Tata", 7.99);
        map.put("Maruthi", 6.34);
        map.put("Honda", 5.78);
        map.put("Bajaj", 8.0);
        map.put("Suzuki", 3.99);

        System.out.println("unsorted map: " + map);

        sorted_map.putAll(map);

        System.out.println("results: " + sorted_map);
    }
}

class ValueComparator implements Comparator<String> {

    Map<String, Double> base;

    public ValueComparator(Map<String, Double> base) {
        this.base = base;
    }

    // Note: this comparator imposes orderings that are inconsistent with
    // equals.
    @Override
    public int compare(String a, String b) {
        if (base.get(a) > base.get(b)) {
            return -1;
        } else if (base.get(a) == base.get(b)) {
            System.out.println();
            if (a.compareTo(b) == -1) {
                return -1;
            } else if (a.compareTo(b) == 1) {
                return 1;
            } else {
                return 0;
            }
        } else {
            return 1;
        } // returning 0 would merge keys
    }
}
4
  • "I tried to use a comparator, but its not giving expected results." - example? Commented Jun 29, 2015 at 6:53
  • Look at this example : beginnersbook.com/2013/12/… Commented Jun 29, 2015 at 6:59
  • but that example doesnt explain if there is a tie in the value :( Commented Jun 29, 2015 at 7:01
  • That logic you can modify according to your needs Commented Jun 29, 2015 at 7:03

3 Answers 3

2

Here you have two problems in your compare implementation. First, you compare boxed Double values with ==:

else if(base.get(a) == base.get(b))

You should replace this with

else if(base.get(a).equals(base.get(b)))

Second, you check a.compareTo(b) for specific values like -1 and 1, but it may return any positive/negative numbers. It's better and simpler just to return the result of a.compareTo(b) instead. Here's the fixed compare method:

public int compare(String a, String b) {
    if (base.get(a) > base.get(b)) {
        return -1;
    } else if (base.get(a).equals(base.get(b))) {
        return a.compareTo(b);
    } else {
        return 1;
    } // returning 0 would merge keys
}

If you want to sort the keys with the same value in case-insensitive manner, just use compareToIgnoreCase:

public int compare(String a, String b) {
    if (base.get(a) > base.get(b)) {
        return -1;
    } else if (base.get(a).equals(base.get(b))) {
        return a.compareToIgnoreCase(b);
    } else {
        return 1;
    } // returning 0 would merge keys
}
Sign up to request clarification or add additional context in comments.

2 Comments

It works, but this is pushing the lower case string(keys) to the bottom, like Ford, Nike,Sears,Suzuki,bmw. Any idea why?
@xtreme, sorry, I was a little bit wrong about what is the problem of your method. I updated the solution and added case-insensitive version as well.
0

As the sorting order relies on both value and key, use the Map.Entry<String, Double> entries:

List<Map.Entry<String, Double>> entries = new ArrayList<>(base.entrySet());
Collections.sort(entries, new Comparator<Map<String, Double>>() {
    ...
});

Comments

0

Just little bit twisted your compare method of ValueComparator class. This will first sort on values & if values are same then sorting on keys. Hope this helps. Output would be something like below:

unsorted map: {Adidas=4.99, Bajaj=8.0, Apple=2.99, Ford=3.99, Puma=1.99, Tata=7.99, Nike=3.99, Suzuki=3.99, Honda=5.78, Kmart=5.99, Maruthi=6.34, Sears=3.99}

results: {Bajaj=8.0, Tata=7.99, Maruthi=6.34, Kmart=5.99, Honda=5.78, Adidas=4.99, Ford=3.99, Nike=3.99, Sears=3.99, Suzuki=3.99, Apple=2.99, Puma=1.99}

import java.util.*;

public class SortValueMap {

    public static void main(String[] args) {

        HashMap<String, Double> map = new HashMap<String, Double>();
        ValueComparator bvc = new ValueComparator(map);
        TreeMap<String, Double> sorted_map = new TreeMap<String, Double>(bvc);

        map.put("Adidas", 4.99);
        map.put("Nike", 3.99);
        map.put("Puma", 1.99);
        map.put("Ford", 3.99);
        map.put("Apple", 2.99);
        map.put("Sears", 3.99);
        map.put("Kmart", 5.99);
        map.put("Tata", 7.99);
        map.put("Maruthi", 6.34);
        map.put("Honda", 5.78);
        map.put("Bajaj", 8.0);
        map.put("Suzuki", 3.99);

        System.out.println("unsorted map: " + map);

        sorted_map.putAll(map);

        System.out.println("results: " + sorted_map);
    }
}

class ValueComparator implements Comparator<String> {

    Map<String, Double> base;

    public ValueComparator(Map<String, Double> base) {
        this.base = base;
    }

    // Note: this comparator imposes orderings that are inconsistent with
    // equals.
    @Override
    public int compare(String a, String b) {
        if(base.get(a).compareTo(base.get(b)) != 0) {
            if (base.get(a) > base.get(b)) {
                return -1;
            } else { 
                return 1;
            }
        }
        return a.compareTo(b);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.