Calculate the frequencies of the strings into a map, find the entry with max value, and return it.
With Stream API this could look like this:
public static String getEventWinner(List<Game> games) {
return games.stream()
.map(Game::getWinner) // Stream<String>
.collect(Collectors.groupingBy(
winner -> winner, LinkedHashMap::new,
Collectors.summingInt(x -> 1)
)) // build the frequency map
.entrySet().stream()
.max(Map.Entry.comparingByValue()) // Optional<Map.Entry<String, Integer>>
.map(Map.Entry::getKey) // the key - winner name
.orElse(null);
}
Here LinkedHashMap
is used as a tie breaker, however, it allows to select as a winner the person who appeared earlier in the game list.
Test:
System.out.println(getEventWinner(Arrays.asList(
new Game("John"), new Game("Zach"), new Game("Zach"),
new Game("Chad"), new Game("John"), new Game("Jack")
)));
// output John
If it is needed to define the winner the person who achieved the maximum number of wins earlier, another loop-based solution should be used:
public static String getEventWinnerFirst(List<Game> games) {
Map<String, Integer> winMap = new HashMap<>();
String resultWinner = null;
int max = -1;
for (Game game : games) {
String winner = game.getWinner();
int tempSum = winMap.merge(winner, 1, Integer::sum);
if (max < tempSum) {
resultWinner = winner;
max = tempSum;
}
}
return resultWinner;
}
For the same input data, the output will be Zach
because he occurred twice in the list earlier than John
.
Update 2
It may be possible to find the earliest achiever of the max result using Stream but a temporary map needs to be created to store the number of wins:
public static String getEventWinner(List<String> games) {
Map<String, Integer> tmp = new HashMap<>();
return games.stream()
.map(Game::getWinner) // Stream<String>
.map(winner -> Map.entry(winner, tmp.merge(winner, 1, Integer::sum))) // store sum in tmp map
.collect(Collectors.maxBy(Map.Entry.comparingByValue()))
.map(Map.Entry::getKey) // the key - winner name
.orElse(null);
}