Sorting HashMap by values [duplicate]
Solution 1:
Try below code it works fine for me. You can choose both Ascending as well as descending order
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class SortMapByValue
{
public static boolean ASC = true;
public static boolean DESC = false;
public static void main(String[] args)
{
// Creating dummy unsorted map
Map<String, Integer> unsortMap = new HashMap<String, Integer>();
unsortMap.put("B", 55);
unsortMap.put("A", 80);
unsortMap.put("D", 20);
unsortMap.put("C", 70);
System.out.println("Before sorting......");
printMap(unsortMap);
System.out.println("After sorting ascending order......");
Map<String, Integer> sortedMapAsc = sortByComparator(unsortMap, ASC);
printMap(sortedMapAsc);
System.out.println("After sorting descindeng order......");
Map<String, Integer> sortedMapDesc = sortByComparator(unsortMap, DESC);
printMap(sortedMapDesc);
}
private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap, final boolean order)
{
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());
// Sorting the list based on values
Collections.sort(list, new Comparator<Entry<String, Integer>>()
{
public int compare(Entry<String, Integer> o1,
Entry<String, Integer> o2)
{
if (order)
{
return o1.getValue().compareTo(o2.getValue());
}
else
{
return o2.getValue().compareTo(o1.getValue());
}
}
});
// Maintaining insertion order with the help of LinkedList
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list)
{
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
public static void printMap(Map<String, Integer> map)
{
for (Entry<String, Integer> entry : map.entrySet())
{
System.out.println("Key : " + entry.getKey() + " Value : "+ entry.getValue());
}
}
}
Edit: Version 2
Used new java feature like stream for-each etc
Map will be sorted by keys if values are same
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
public class SortMapByValue
{
private static boolean ASC = true;
private static boolean DESC = false;
public static void main(String[] args)
{
// Creating dummy unsorted map
Map<String, Integer> unsortMap = new HashMap<>();
unsortMap.put("B", 55);
unsortMap.put("A", 20);
unsortMap.put("D", 20);
unsortMap.put("C", 70);
System.out.println("Before sorting......");
printMap(unsortMap);
System.out.println("After sorting ascending order......");
Map<String, Integer> sortedMapAsc = sortByValue(unsortMap, ASC);
printMap(sortedMapAsc);
System.out.println("After sorting descending order......");
Map<String, Integer> sortedMapDesc = sortByValue(unsortMap, DESC);
printMap(sortedMapDesc);
}
private static Map<String, Integer> sortByValue(Map<String, Integer> unsortMap, final boolean order)
{
List<Entry<String, Integer>> list = new LinkedList<>(unsortMap.entrySet());
// Sorting the list based on values
list.sort((o1, o2) -> order ? o1.getValue().compareTo(o2.getValue()) == 0
? o1.getKey().compareTo(o2.getKey())
: o1.getValue().compareTo(o2.getValue()) : o2.getValue().compareTo(o1.getValue()) == 0
? o2.getKey().compareTo(o1.getKey())
: o2.getValue().compareTo(o1.getValue()));
return list.stream().collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> b, LinkedHashMap::new));
}
private static void printMap(Map<String, Integer> map)
{
map.forEach((key, value) -> System.out.println("Key : " + key + " Value : " + value));
}
}
Solution 2:
Assuming Java, you could sort hashmap just like this:
public LinkedHashMap<Integer, String> sortHashMapByValues(
HashMap<Integer, String> passedMap) {
List<Integer> mapKeys = new ArrayList<>(passedMap.keySet());
List<String> mapValues = new ArrayList<>(passedMap.values());
Collections.sort(mapValues);
Collections.sort(mapKeys);
LinkedHashMap<Integer, String> sortedMap =
new LinkedHashMap<>();
Iterator<String> valueIt = mapValues.iterator();
while (valueIt.hasNext()) {
String val = valueIt.next();
Iterator<Integer> keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Integer key = keyIt.next();
String comp1 = passedMap.get(key);
String comp2 = val;
if (comp1.equals(comp2)) {
keyIt.remove();
sortedMap.put(key, val);
break;
}
}
}
return sortedMap;
}
Just a kick-off example. This way is more useful as it sorts the HashMap and keeps the duplicate values as well.
Solution 3:
In Java 8:
Map<Integer, String> sortedMap =
unsortedMap.entrySet().stream()
.sorted(Entry.comparingByValue())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));
Solution 4:
map.entrySet().stream()
.sorted((k1, k2) -> -k1.getValue().compareTo(k2.getValue()))
.forEach(k -> System.out.println(k.getKey() + ": " + k.getValue()));