1

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?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Cannonball
  • 43
  • 7
  • Does this answer your question? [sort hashtable by values](https://stackoverflow.com/questions/5176771/sort-hashtable-by-values) – Joe Jan 02 '22 at 12:38
  • @Joe this only sorts a hash with one value and i want to know how to put two values in and get the highest one by considering the time and kills. – Cannonball Jan 02 '22 at 12:43
  • Then would augmenting it with https://stackoverflow.com/questions/4258700/collections-sort-with-multiple-fields solve your issue? – Joe Jan 02 '22 at 12:44
  • _ put two values in to get the highest one_ have you `compare` method return a value based on the two integers. For more help post [mre] and include hard coded test data – c0der Jan 02 '22 at 13:16
  • @Joe not quite actually. – Cannonball Jan 02 '22 at 13:26
  • Hashtable is considered an outdated class, and it would be better to use a HashMap. – Mark Rotteveel Jan 02 '22 at 13:33

2 Answers2

0

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));
Ma3x
  • 5,761
  • 2
  • 17
  • 22
  • It says: The method sorted(Comparator super Integer>) in the type Stream is not applicable for the arguments (Comparator) while using the myValuesComparator variable in sorted. – Cannonball Jan 02 '22 at 13:39
  • The `hash.values().stream()` should be a `Stream` (and not a `Stream`), since you specified it as `Map hash = new Hashtable();`in your question. I just copied your code. If that is not the case post all relevant code. – Ma3x Jan 02 '22 at 13:44
  • Thanks, it seems to be working like intended, i have one more question, how can i show the String Key in output without adding the variable in the class? – Cannonball Jan 02 '22 at 14:14
  • @Cannonball I edited the whole post, to include the key as well. – Ma3x Jan 02 '22 at 14:15
-3

Set keys = hash.keySet();

keys.stream().forEach(System.out::println);

Mohan k
  • 68
  • 4