patternjavaMinor
Finding the keys of map with the highest values (equality may occur)
Viewed 0 times
maptheequalitymaywithoccurkeysfindingvalueshighest
Problem
I am currently implementing a Poker game, I have created all the logic for getting the rank of a hand, and I now have to determine the winner of a given hand.
Due to this being Poker, there may be multiple winners in a round. I, therefore, need to find all the keys (
However, I am using Java 8 and thus a lot of streams. I couldn't figure out a (pretty) way to implementing the above in streams, and therefore ended up coding it in a loop. I welcome any suggestions, especially those related to writing it succinctly and efficiently using Java 8 streams.
Due to this being Poker, there may be multiple winners in a round. I, therefore, need to find all the keys (
Player) that have the best hand (regardless of how many there are).public Map determineWinner(Map hands) {
// Initialize worst possible hand (any hand beats this) - less verbose than
// having to get a random element form the map
Hand currentBestHand = new Hand(RankType.HIGH_CARD, CardRank.DEFAULT, new ArrayList<>(), new ArrayList<>());
Map bestHands = new HashMap<>();
for (Map.Entry playerAndHand : hands.entrySet()) {
int comparisonValue = playerAndHand.getValue().compareTo(currentBestHand);
if (comparisonValue > 0) {
currentBestHand = playerAndHand.getValue();
bestHands.clear();
bestHands.put(playerAndHand.getKey(), playerAndHand.getValue());
} else if (comparisonValue == 0) {
bestHands.put(playerAndHand.getKey(), playerAndHand.getValue());
}
}
return bestHands;
}However, I am using Java 8 and thus a lot of streams. I couldn't figure out a (pretty) way to implementing the above in streams, and therefore ended up coding it in a loop. I welcome any suggestions, especially those related to writing it succinctly and efficiently using Java 8 streams.
Solution
To use streams you'd have to make the score part of the object (at least on an intermediate level) so that you can find the maximum based on the score.
Here's a little example based on a string/string map and String.length() as score replacement (as I don't have your original objects). Should be sufficient to illustrate the idea:
... or, after a few inlines of intermediate variables:
Is this better than the loop: I don't personally think so. My advice: stick to your loop or revise your data structures to better support this approach.
Here's a little example based on a string/string map and String.length() as score replacement (as I don't have your original objects). Should be sufficient to illustrate the idea:
Map m = ...
Map>> intermediateByScore = m.entrySet().stream()
.collect(Collectors.groupingBy(e -> e.getValue().length()));
Entry>> highest = intermediateByScore.entrySet().stream()
.sorted((e1, e2) -> e2.getKey().compareTo(e1.getKey()))
.findFirst()
.get();
Map result = highest.getValue().stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));... or, after a few inlines of intermediate variables:
Map result = m.entrySet().stream()
.collect(Collectors.groupingBy(e -> e.getValue().length()))
.entrySet().stream()
.sorted((e1, e2) -> e2.getKey().compareTo(e1.getKey()))
.findFirst()
.get().getValue().stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));Is this better than the loop: I don't personally think so. My advice: stick to your loop or revise your data structures to better support this approach.
Code Snippets
Map<String, String> m = ...
Map<Integer, List<Entry<String, String>>> intermediateByScore = m.entrySet().stream()
.collect(Collectors.groupingBy(e -> e.getValue().length()));
Entry<Integer, List<Entry<String, String>>> highest = intermediateByScore.entrySet().stream()
.sorted((e1, e2) -> e2.getKey().compareTo(e1.getKey()))
.findFirst()
.get();
Map<String, String> result = highest.getValue().stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));Map<String, String> result = m.entrySet().stream()
.collect(Collectors.groupingBy(e -> e.getValue().length()))
.entrySet().stream()
.sorted((e1, e2) -> e2.getKey().compareTo(e1.getKey()))
.findFirst()
.get().getValue().stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));Context
StackExchange Code Review Q#153346, answer score: 3
Revisions (0)
No revisions yet.