【问题标题】:Counting objects with a same property value计数具有相同属性值的对象
【发布时间】:2015-06-30 20:03:42
【问题描述】:

我正在创建一个扑克等级求解器,我必须计算一组卡片中具有相同花色或相同等级的卡片。在这里,我创建HashMap 并在集合中有多个等级时增加值。

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);
    }

我想知道是否可以使用流与 java 流做完全相同的事情。它看起来像这样:

    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);
    }

【问题讨论】:

    标签: java hashmap java-8 java-stream


    【解决方案1】:

    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);
    
    }
    

    基本上你按等级对卡片进行分组,这样你就有一个Map&lt;Rank, List&lt;Card&gt;&gt;

    然后您使用下游收集器counting() 将每个列表映射到其元素数量,以便最终结果为Map&lt;Rank, Long&gt;(如果您确实需要,也可以使用summingInt(i -&gt; 1) 而不是counting()有一个Map&lt;Rank, Integer&gt;)。

    【讨论】:

    • 作为附录,如果Rank 是enum,使用.collect(groupingBy(Card::getRank, ()-&gt;new EnumMap(Rank.class), counting())) 可能会更有效。
    【解决方案2】:

    看起来你正在寻找类似的东西

    return cards.stream()
            .collect(Collectors.toMap(Card::getRank, e -> 1, Integer::sum))
            //                        keyMapper, valueMapper, mergeFunction
            .containsValue(4);
    

    【讨论】:

    • 对我来说,.collect(Collectors.groupingBy(Card::getRank, Collectors.counting()) 看起来更干净……
    • @Holger 其实对我来说也是。在发布此答案并根据当前和有限的知识创建代码时没有意识到这一点。无论如何,您似乎对 Java 8 了解很多。请问您的知识来自哪里?您能否在官方教程(书籍或网站/文章)旁边推荐有关它的良好信息来源?
    • @Pshemo:不幸的是,我不记得读过比官方材料好得多的东西,所以我手头没有推荐。它现在只是玩了两年,因为试图回答一个 SO 问题意味着参与其中,每个问题都让我变得更好☺ 我回答了近四百个,不包括我读过和思考过的那些,但是没有回答,因为其他人更快......
    • @Holger 感谢您的回复。 “现在才玩了两年”,所以您似乎甚至在 Java 8 正式发布之前(即 2014 年 3 月)就对它感兴趣了。这很有意义并解释了您的知识:)
    猜你喜欢
    • 2022-07-03
    • 1970-01-01
    • 2013-10-14
    • 2018-09-20
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 2019-06-05
    相关资源
    最近更新 更多