Issue
I have a system to check to sort by value in a Hashtable and it is used to get the top Strings in that Hashtable. I want to set another value in that Hashtable, so I am using a class inside, like that:
Map<String, Values> hash = new Hashtable<String,Values>();
The class:
public class Values {
public Integer a;
public Integer b;
public Values(Integer a, Integer b) {
this.a = a;
this.b = b;
}
}
My objective is sorting all the values in the Hashtable (Integer a and b) and returning the Hashtable String showing who has the highest values, (like a database system) is it possible to do that? The reason I want to do that is for getting the best killers in a game sorting by Integer a and set the time when the last kill was done in Integer b, so if the player has killed before the other and has the same amount of kills it shows the one with the highest Integer b at first, which would be the one with the highest time (milliseconds) in the variable b.
What would be the best method to do something like that?
Solution
EDIT: Edited the post to sort the whole entrySet()
instead.
To get a custom sort order you would define a Comparator<Map.Entry<String, Values>>, specifying the order in what you would like to compare the entries from your map, and if any part of the sort should be done in reverse (descending).
From your description I think you wanted a
to be the first to be sorted descending and then b
to be sorted descending as well.
Comparator<Map.Entry<String, Values>> myValuesComparator = Comparator
.comparingInt((Map.Entry<String, Values> entry) -> entry.getValue().a)
.thenComparingInt(entry -> entry.getValue().b)
.reversed();
Then you turn your hash.entrySet()
into a stream by calling .stream()
and then you sort the stream of entries with your comparator by calling .sorted(myValuesComparator)
. In the end you collect the sorted entries into a new collection, we will collect them into a List<Map.Entry<String, Values>>
here.
List<Map.Entry<String, Values>> list = hash.entrySet()
.stream()
.sorted(myValuesComparator)
.collect(Collectors.toList());
If you want to check the result you can place a breakpoint and check the elements inside the list or just print the whole list
for (Map.Entry<String, Values> entry : list) {
System.out.printf("Key: %s, score: %d, time of last update: %d%n", entry.getKey(), entry.getValue().a, entry.getValue().b);
}
This same code also works if you change your Hashtable
to a HashMap
, as suggested by Mark Rotteveel in the comments, since Hashtable
is considered an outdated class.
Here is my sample output
Key: Test9, score: 11, time of last update: 3
Key: Test8, score: 11, time of last update: 2
Key: Test7, score: 11, time of last update: 1
Key: Test6, score: 10, time of last update: 3
Key: Test5, score: 10, time of last update: 2
Key: Test4, score: 10, time of last update: 1
Key: Test3, score: 1, time of last update: 3
Key: Test2, score: 1, time of last update: 2
Key: Test1, score: 1, time of last update: 1
for input
hash.put("Test1", new Values( 1, 1));
hash.put("Test2", new Values( 1, 2));
hash.put("Test3", new Values( 1, 3));
hash.put("Test4", new Values(10, 1));
hash.put("Test5", new Values(10, 2));
hash.put("Test6", new Values(10, 3));
hash.put("Test7", new Values(11, 1));
hash.put("Test8", new Values(11, 2));
hash.put("Test9", new Values(11, 3));
Answered By - Ma3x