Hello guys i have a hash map like a:1,c:2,d:3,b:2 and i want to sort it like d:3,b:2,c:2,a:1, descending in values and alphabetical order in keys how can i do it i would be grateful for any help thanks!
-
Can you demonstrate any effort at solving this yourself?Scott Hunter– Scott Hunter2021-04-09 23:52:47 +00:00Commented Apr 9, 2021 at 23:52
-
Hey Dante, welcome ! Have you tried something already? It would be nice to start with something existing to help you furtherYassin Hajaj– Yassin Hajaj2021-04-09 23:52:51 +00:00Commented Apr 9, 2021 at 23:52
-
I reopened because the supposed duplicate is about simple sorting of a map. This question is more complex, asking to sort first by values and then by keys.Basil Bourque– Basil Bourque2021-04-10 08:03:25 +00:00Commented Apr 10, 2021 at 8:03
3 Answers
Sort the following in descending order of values then keys. I amended the list to make it more interesting.
Map<String, Integer> map = Map.of("a", 8, "b", 2, "c", 4, "d",
8, "e", 3, "f", 4, "g", 7, "h", 1, "i", 5, "j", 2);
First define a Comparator to use in sorting the Map entries. Each entry is represented by the Map.Entry class. That class offers methods comparingByValue() and comparingByKey().
The following code says, first sort by value, then by the key. These are sorted in natural order except the following reversed() method says reverse the sorting of all comparators prior. So the values will be sorted in reversed order and the keys in alphabetical order.
Comparator<Entry<String, Integer>> comp = Entry
.<String, Integer>comparingByValue().reversed()
.thenComparing(Entry.comparingByKey());
This streams the existing map's entrys and applies the comparator to the sort method. It then collects them in a linked hashMap to preserve the order. The merge function does not play a part in this but is syntactically required.
Map<String, Integer> lhmap =
map.entrySet().stream().sorted(comp)
.collect(Collectors.toMap(Entry::getKey,
Entry::getValue,
(a, b) -> a, // merge function
LinkedHashMap::new));
lhmap.entrySet().forEach(System.out::println);
That code prints:
a=8
d=8
g=7
i=5
c=4
f=4
e=3
b=2
j=2
h=1
3 Comments
Comparator<Map.Entry<String, Integer>> firstwithvaluessecoundwiththekeys = Map.Entry .<String, Integer>comparingByValue().reversed() .thenComparing(Map.Entry.comparingByKey()); I have solved my question thanks everyone again!A HashMap is not necessarily ordered, and in fact does not guarantee that the key value pair orders wil lremain constant over time. From the docs:
Hash table based implementation of the Map interface. This implementation provides all of the optional map operations, and permits null values and the null key. (The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.) This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.
If you want a sorted map, use a NavigableMap or SortedMap. There are a few options. TreeMap is probably the simplest.
A Red-Black tree based NavigableMap implementation. The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used.
So to create a map with the keys in descending alphabetical order something like this should do the tick:
Comparator<String> comparator = new Comparator<>() {
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
};
TreeMap<String, Integer> treeMap = new TreeMap<>(comparator);
2 Comments
HashMap, so I gave them a simple example of creating a sorted map. I read the "descending in values and alphabetical order in keys" section as a description of the map in part because sorting on keys, and then values does not make much sense given that keys in a HashMap are unique and sorting matching keys on value is a non-issue. That could be misinterpretation on my part. I appreciate you additions to my answer, they were definitely helpful!This answer is using java 8 streams.
//LinkedHashMap preserve the ordering of elements in which they are inserted
LinkedHashMap<String, Integer> reverseSortedMap = new LinkedHashMap<>();
unSortedMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.forEachOrdered(x -> reverseSortedMap.put(x.getKey(), x.getValue()));
System.out.println("Reverse Sorted Map : " + reverseSortedMap);