Sort HashMap with duplicate values

10,717

Solution 1

You are using TreeSet<Integer> sortedSet

SETS by definition will not allow duplicates.

Here is an example that is Sorting by Value like you expect without losing any of the Entries.

import java.util.*;

public class Test {

public static Map<String, Integer> sortByValueDesc(Map<String, Integer> map) {
    List<Map.Entry<String, Integer>> list = new LinkedList(map.entrySet());
    Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
        @Override
        public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
            return o2.getValue().compareTo(o1.getValue());
        }
    });

    Map<String, Integer> result = new LinkedHashMap<>();
    for (Map.Entry<String, Integer> entry : list) {
        result.put(entry.getKey(), entry.getValue());
    }
    return result;
}

    public static void main(String[] args) {

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

        map.put("item1", 1);
        map.put("item2", 2);
        map.put("item3", 1);
        map.put("item4", 7);
        map.put("item5", 3);
        map.put("item6", 4);

        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println("Item is:" + entry.getKey() + " with value:"
                    + entry.getValue());
        }

        System.out.println("*******");

        Map<String,Integer> sortedMap = sortByValueDesc(map);

        for (Map.Entry<String, Integer> entry : sortedMap.entrySet()) {
            System.out.println("Item is:" + entry.getKey() + " with value:"
                    + entry.getValue());
        }

    }

}

The result I am Getting is (Now That I check you want greater values to be first):

Item is:item4 with value:7
Item is:item2 with value:2
Item is:item3 with value:1
Item is:item1 with value:1
Item is:item6 with value:4
Item is:item5 with value:3
*******
Item is:item4 with value:7
Item is:item6 with value:4
Item is:item5 with value:3
Item is:item2 with value:2
Item is:item3 with value:1
Item is:item1 with value:1

For why you are losing one element here is your problem:

//HERE YOU ARE GETTING ALL THE VALUES
List<Integer> mapValues = new ArrayList<Integer>(tempMap.values());
HashMap<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();

//YOU ARE INSERTING THE VALUES TO A TreeSet WHICH WILL REMOVE DUPLICATES
TreeSet<Integer> sortedSet = new TreeSet<Integer>(mapValues);

Solution 2

I believe you need treeMap. It does not allow duplicates, and takes comparable as a key. Sorts according to compareTo() if it is comparable, if not then Asks comparator in constructor. Map DOES NOT allow duplicates

    Map<String,Integer> mymap = new TreeMap<String,Integer>();
    mymap.put("item1", 5);
    mymap.put("item2", 1);
    mymap.put("item3", 7);
    mymap.put("item4", 1);

for(Map.Entry<String, Integer> entry: mymap.entrySet())
            System.out.println("Item is:" + entry.getKey() + " with value:" + 
                    entry.getValue());
Share:
10,717
Eme Emertana
Author by

Eme Emertana

Updated on June 09, 2022

Comments

  • Eme Emertana
    Eme Emertana almost 2 years

    Hi I am using following code to sort my HashMap, it sorts the map correctly but does not count the repeated values,

    Map<String, Integer> mymap = new HashMap<String, Integer>();
    mymap.put("item1", 5);
    mymap.put("item2", 1);
    mymap.put("item3", 7);
    mymap.put("item4", 1);
    
    Map<String, Integer> tempMap = new HashMap<String, Integer>();
    for (String wsState : mymap.keySet()) {
        tempMap.put(wsState, mymap.get(wsState));
    }
    
    List<String> mapKeys = new ArrayList<String>(tempMap.keySet());
    List<Integer> mapValues = new ArrayList<Integer>(tempMap.values());
    HashMap<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
    TreeSet<Integer> sortedSet = new TreeSet<Integer>(mapValues);
    Object[] sortedArray = sortedSet.toArray();
    int size = sortedArray.length;
    for (int i = 0; i < size; i++) {
        sortedMap.put(mapKeys.get(mapValues.indexOf(sortedArray[i])),
                (Integer) sortedArray[i]);
    }
    for (Map.Entry<String, Integer> entry : mymap.entrySet())
        System.out.println("Item is:" + entry.getKey() + " with value:"
                + entry.getValue());
    
    System.out.println("***");
    
    for (Map.Entry<String, Integer> entry : sortedMap.entrySet())
        System.out.println("Item is:" + entry.getKey() + " with value:"
                + entry.getValue());
    

    Result is as following (the item 4 is not shown because its value is same as item2's !!!) :

    Item is:item4 with value:1
    Item is:item2 with value:1
    Item is:item3 with value:7
    Item is:item1 with value:5
    ***
    Item is:item2 with value:1
    Item is:item1 with value:5
    Item is:item3 with value:7
    

    It is a HashMap and need to be sorted by value. Expected output is :

    Item is:item3 with value:7
    Item is:item1 with value:5
    Item is:item2 with value:1
    Item is:item4 with value:1
    

    OR

    Item is:item2 with value:1
    Item is:item4 with value:1
    Item is:item1 with value:5
    Item is:item3 with value:7
    
  • Eme Emertana
    Eme Emertana over 11 years
    but its duplicate of values not keys.
  • gtgaxiola
    gtgaxiola over 11 years
    @EmeEmertana Edit my answer also to address why You are losing one value
  • chao
    chao almost 9 years
    Your example still doesn't work like intended. It still returns the values in a non-descending order (I got 10,10,10,10,3,4,3,10,10,6,1,1 after applying your sortByValue method).
  • gtgaxiola
    gtgaxiola almost 9 years
    @chao please describe how are you inserting and sorting.. I just ran this code from 3 years ago and it worked on the input provided by your comment. (10,10,10,10,6,4,3,3,1,1)