0
votes

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
I think you are trying to convert the keySet() (which is a set of Strings) to a List<Integer> in the very first line of code in this method... Maybe you want UnsortedMap.values() instead? - deHaar
sortedMap.put(UnsortedMap.toString(), keys); - what is this supposed to do? - Amongalen
Btw. in Java 8 and up you can do it in much simplier way using Streams. Check out this answer: stackoverflow.com/a/27860358/4949750 - Amongalen
@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

2 Answers

0
votes

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;

}

0
votes

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.