0

I am trying to sort a hashmap that has a structure of by the value from high to Low.

I have created a function below to sort the data.

public static void SortDataHighToLow (Map <String, Integer> UnsortedMap){
    List <Integer> list = new ArrayList(UnsortedMap.keySet());
    Collections.sort(list,new Comparator <Integer>(){

        @Override
        public int compare(Integer arg0, Integer arg1) {

            return arg0-arg1;
        }
    });

    Map <String, Integer> sortedMap = new LinkedHashMap<>();

    for (Integer keys: list){
        sortedMap.put(UnsortedMap.toString(), keys);
    }

    System.out.println(sortedMap);
}

I am recieving the error below:

Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer (java.lang.String and java.lang.Integer are in module java.base of loader 'bootstrap')

I believe my error is caused by the for() above that I cannot read the Key value.

What adjustment should I make?

Thanks for the help.

  • 2
    So do you want to sort by key or by value? You're taking `keySet` - collection of Strings - and define a Comparator of Integers. – Amongalen May 18 '20 at 08:54
  • 2
    I think you are trying to convert the `keySet()` (which is a set of `String`s) to a `List` in the very first line of code in this method... Maybe you want `UnsortedMap.values()` instead? – deHaar May 18 '20 at 08:54
  • 1
    `sortedMap.put(UnsortedMap.toString(), keys);` - what is this supposed to do? – Amongalen May 18 '20 at 08:55
  • 1
    Btw. in Java 8 and up you can do it in much simplier way using Streams. Check out this answer: https://stackoverflow.com/a/27860358/4949750 – Amongalen May 18 '20 at 08:58
  • Hashmap is probably not the best data structure for it. But you might want to create a treemap using your value as key? – Vargan May 18 '20 at 08:58
  • 1
    @deHaar when I put `sortedMap.put(UnsortedMap.values()` it gives Collection cannot be converted to string error. Thats why I attempted UnsortedMap.toString() but I am pretty sure I am wrong. – Utku Tarhan May 18 '20 at 08:58
  • ava sort Map by key (ascending and descending orders). https://howtodoinjava.com/sort/java-sort-map-by-key/ – Kumar Anil Chaurasiya May 18 '20 at 08:59
  • @Amongalen This is for my data structures class, there is probably a simplier way to do it, but class wants to stick us to the data structures. – Utku Tarhan May 18 '20 at 08:59
  • 2
    @UtkuTarhan You do know that your map has Strings as keys and Integers as values, right? Because both in your code and comments here it seems like you seem to think the keys are Integers. – OH GOD SPIDERS May 18 '20 at 09:01
  • 1
    Data structures stay the same, you just use different method to process them. Or did they say you have to implement your own comparator and use for loops? – Amongalen May 18 '20 at 09:02
  • @OHGODSPIDERS so my input format is when I am comparing I want to sort the integers from high to low. I might have declared that incorrectly as it is the first time I am working with HashKeys. – Utku Tarhan May 18 '20 at 09:04
  • 1
    Have a look at [this question](https://stackoverflow.com/questions/109383/sort-a-mapkey-value-by-values), it is about nearly the same problem (plus an additional one). – deHaar May 18 '20 at 09:06
  • 1
    @deHaar The answer to the question worked, appreciated the help. – Utku Tarhan May 18 '20 at 09:12

2 Answers2

0

This is a comparator that do the job:

public class MapKeyByValueComparator<K, T> implements Comparator<K> {

    private final Map<K, T> map;

    private final Comparator<T> comparator;

    public MapKeyByValueComparator(Map<K, T> map, Comparator<T> comparator) {
        this.map = map;
        this.comparator = comparator;
    }

    @Override
    public int compare(K o1, K o2) {
        int ritem = comparator.compare(map.get(o1), map.get(o2));
        // CAN NOT RETURNS 0, otherwise key with the same value will be overridden
        if (ritem == 0) {
            ritem = 1;
        }
        return ritem;
    }

}

And then you can use a TreeMap as:

Map<something, somethig> map = new TreeMap<>(comparator):
map.addAll(...);

But PAY ATTENTION, this brokes the contract of Comparable

It is strongly recommended (though not required) that natural orderings be consistent with equals. This is so because sorted sets (and sorted maps) without explicit comparators behave "strangely" when they are used with elements (or keys) whose natural ordering is inconsistent with equals. In particular, such a sorted set (or sorted map) violates the general contract for set (or map), which is defined in terms of the equals method.

Renato
  • 2,077
  • 1
  • 11
  • 22
0

Upon the answer came from @deHaar my problem got resolved. The code is below.

private static <K, V> Map<K, V> sortByValue(Map<K, V> map) {
List<Entry<K, V>> list = new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Object>() {
    @SuppressWarnings("unchecked")
    public int compare(Object o1, Object o2) {
        return ((Comparable<V>) ((Map.Entry<K, V>) (o1)).getValue()).compareTo(((Map.Entry<K, V>) (o2)).getValue());
    }
});

Map<K, V> result = new LinkedHashMap<>();
for (Iterator<Entry<K, V>> it = list.iterator(); it.hasNext();) {
    Map.Entry<K, V> entry = (Map.Entry<K, V>) it.next();
    result.put(entry.getKey(), entry.getValue());
}

return result;

}