How sort HashMap entries by multiple properties.
Suppose I have a map with key String and value as Object.
Map<String, UserMetrics> map = new HashMap<>
map.put("user10",new UserMetrics(1,100,111));
map.put("user3",new UserMetrics(10,330,444));
map.put("user11",new UserMetrics(333,100,555));
map.put("user1",new UserMetrics(1,111,433));
public static class UsageMetrics implements Serializable {
private long param1;
private long param2;
private long param3;....
}
I want to sort users first by "param1" and then after by "param2"
result expected:<>
user10, UserMetrics(1,100,111)
user1, UserMetrics(1,111,433))
user3, UserMetrics(10,330,444));
user11, UserMetrics(333,100,555))
You can use the following comparator for sorting:
Comparator
.comparingLong(UserMetrics::getParam1)
.thenComparingLong(UserMetrics::getParam2);
The difficulty is, however that you want to sort values, not keys. It seems also you need both keys and values. For this you could make and sort a copy of the entry set of your map. Something along the lines:
List<Map.Entry<String, UserMetrics>> sortedEntries = new ArrayList<>(map.entrySet());
Collections.sort(sortedEntries,
Map.Entry.comparingByValue(
Comparator
.comparingLong(UserMetrics::getParam1)
.thenComparingLong(UserMetrics::getParam2)));
Alternatively you can also use a sorted collection (like TreeSet
) or a sorted stream - normally you can provide your own comparator to the "sorting things".
Also note that I'm using comparingLong
/thenComparingLong
, unlike other answers where people just used comparing
/thenComparing
. The problem with comparing
/thenComparing
is that if you have primitive types like long
, comparing
/thenComparing
will essentially box them into wrapper types like Long
, which is totally unnecessary.
You can use below code. I have written by using Employee
the s value object, so you can use your own Object
:
public class Main {
public static void main(String[] args) throws InterruptedException {
HashMap<String, Employee> map = new HashMap<>();
Map<String, Employee> sortedMap = map.entrySet()
.stream()
.sorted(Entry.comparingByValue(Main::compare))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));
}
public static int compare(Employee e1, Employee e2) {
return e1.getAge() - e2.getAge();
}
}
Edited:
Here is another way you can use Comparator#comparing
and thenComparing
to sort.
Map<String, Employee> sortedMap = map.entrySet()
.stream()
.sorted(Entry.comparingByValue(
Comparator.comparing(Employee::getAge)
.thenComparing(Employee::getSalary)))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With