1

I have players named(String name) by their names and I have Lovers(int Lovers).

Each player has a number of lovers. and each player has a unique name. I want a way to sort them by number and if two players or more have the same number of lovers, I want them to be sorted alphabetical order.

I thought about using a Map and Hashmap.

        Map<String, Integer> Players= new HashMap<>();
        Players.put("Christiano Ronaldo",10);
        Players.put("Messi",50);
        Players.put("Kaka",10);
        Players.put("Ronaldinho",100);

        List sortedKeys=new ArrayList(Players.keySet());
        Collections.sort(sortedKeys);

I find this way is not optimal for my case.

What I expect is that get sorted by a number of lovers and if a number of lovers are equal then we sort them by name alphabetical order.

Ihor Patsian
  • 1,288
  • 2
  • 15
  • 25
  • You might consider encapsulating a *player* into a `class Player` with fields `String name` and `List lovers`. Then you can use `Collections.sort()` and pass in a custom `Comparator`. See https://www.mkyong.com/java/java-object-sorting-example-comparable-and-comparator/ – mario_sunny Nov 05 '19 at 20:17

1 Answers1

0

Using java 8 Collections it can look like this, but you might want to create a class as suggested, I just sketch it as an interface. Without Comparator this nested sorting stuff can become rather nasty.

interface Player{
    Integer getLovers();
    public String getName();
}

List<Player> sorted = players.entrySet()
            .stream()
            .map(i -> new Player(i.getKey(), i.getValue()))
            .sorted(Comparator.comparing(Player::getLovers).thenComparing(Player::getName))
            .collect(Collectors.toList());

If you want to have only the list of names, you can map it:

List<String> names = sorted.stream()
            .map(Player::getName)
            .collect(Collectors.toList());

You could also take @Deadpool's direct approach, but avoiding to create another intermediary Map. For the moment the intermediary could just do what you want, but there's no guarantee for its iteration order. At the moment it in fact creates a LinkedHashMap, which preserves order, but that's not guaranteed to stay like that for ever, if the streaming implementation changes.

List<String> names = players.entrySet().stream()
            .sorted(Comparator.comparing(Map.Entry<String, Integer>::getValue)
                    .thenComparing(Map.Entry<String, Integer>::getKey))
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());
Curiosa Globunznik
  • 3,129
  • 1
  • 16
  • 24
  • is that mean I need to create an object for each player? if Yes, is there another way? – Michael Andro Nov 05 '19 at 20:55
  • I said that because the name of players are not fixed. it might be input from the user. so I cannot figure out how many objects I need. – Michael Andro Nov 05 '19 at 21:07
  • I don't know, the variable number of players issue is not so much an issue, I think, I adapted the answer and also added a modified version of the directly-sort-map-entryset-items-approach, just avoiding to create another map in between that could scramble the sort order again. – Curiosa Globunznik Nov 05 '19 at 21:48