Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Counting objects with a same property value

I'm creating a poker rank solver and I have to count cards with same suit or same rank in a set of cards. Here I create HashMap and increment value if multiple ranks are in the set.

private boolean isFourOfAKind() {
        Map<RANK, Integer> rankDuplicates = new HashMap<>();
        for(Card card : cards) {
            rankDuplicates.put(card.getRank(), rankDuplicates.getOrDefault(card.getRank(), 0) + 1);
        }
        return rankDuplicates.containsValue(4);
    }

I was wondering is it possible using streams do exact same things with java streams. It would look something like this:

    private boolean isFourOfAKind() {
        Map<RANK, Integer> rankDuplicates = cards.stream()
            .map(Card::getRank)
            .collect(Collectors.toMap(/*...something goes here..*/)); // of course this is very wrong, but you can see what I'm aiming at.
        return rankDuplicates.containsValue(4);
    }
like image 658
Artūrs Avatar asked Apr 22 '15 22:04

Artūrs


2 Answers

It looks like you are looking for something like

return cards.stream()
        .collect(Collectors.toMap(Card::getRank, e -> 1, Integer::sum))
        //                        keyMapper, valueMapper, mergeFunction
        .containsValue(4);
like image 96
Pshemo Avatar answered Oct 26 '22 06:10

Pshemo


Another variant with groupingBy:

import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;

...

private boolean isFourOfAKind() {
    return cards.stream()
                .collect(groupingBy(Card::getRank, counting()))
                .containsValue(4L);

}

Basically you group the card by the ranks so that you have a Map<Rank, List<Card>>

Then you use the downstream collector counting() to map each list to its number of elements, so that the final result is a Map<Rank, Long> (you could also use summingInt(i -> 1) instead of counting() if you really need to have a Map<Rank, Integer>).

like image 38
Alexis C. Avatar answered Oct 26 '22 07:10

Alexis C.