为了账号安全,请及时绑定邮箱和手机立即绑定

java - 如何使用Java流获得具有相同最大值的所有对象?

java - 如何使用Java流获得具有相同最大值的所有对象?

慕勒3428872 2022-05-21 13:51:38
我有得分的球员。我想获得所有使用流和过滤器共享最大积分的玩家。public class Player {    private int points; // Getter omitted}我可以通过首先获得得分最高的玩家,然后过滤所有得分相同的玩家来做到这一点。Player topPlayer = players.stream().max(Comparator.comparing(Player::getPoints)).orElse(null);players.stream().filter(p -> p.getPoints() == topPlayer.getPoints()).collect(Collectors.toList());这可以用单个谓词/单行来完成吗?
查看完整描述

3 回答

?
LEATH

TA贡献1936条经验 获得超6个赞

您可以收集到TreeMap第一个并且只获取最后一个条目(最大值所在的位置)


players.stream()

       .collect(Collectors.groupingBy(

           Player::getPoints,

           TreeMap::new,

           Collectors.toList()

       ))

       .lastEntry()

       .getValue();


查看完整回答
反对 回复 2022-05-21
?
萧十郎

TA贡献1815条经验 获得超13个赞

首先按点分组,得到一个 Map 结果,然后找到 map 中的 max key。时间成本将为 O(n):


List<Player> players = new ArrayList<>();

players.stream().collect(Collectors.groupingBy(Player::getPoints))

        .entrySet().stream()

        .max(Map.Entry.comparingByKey())

        .ifPresent(System.out::println);


查看完整回答
反对 回复 2022-05-21
?
汪汪一只猫

TA贡献1898条经验 获得超8个赞

这是一个使用自定义收集器的版本。它巨大、丑陋和复杂,但它在O(n)中运行,只对数据进行一次传递,并且几乎不需要额外的空间。


List<Player> highest = players.stream().collect(ArrayList::new, 

    (list, player) -> {

        if (list.isEmpty() || list.get(0).getPoints() == player.getPoints()) {

            list.add(player);

        } else if (list.get(0).getPoints() < player.getPoints()) {

            list.clear();

            list.add(player);

        }

    },

    (l1, l2) -> {

        if (l1.isEmpty()) {

            l1.addAll(l2);

        } else if (!l2.isEmpty()) {

            int cmp = Integer.compare(l1.get(0).getPoints(), l2.get(0).getPoints());

            if (cmp < 0) {

                l1.clear();

                l1.addAll(l2);

            } else if (cmp == 0) {

                l1.addAll(l2);

            }

        }

    });

累加器和组合器具有关联性的证明留给读者作为练习。


编辑:我试图写一个更漂亮的组合器。我设法写了一个更短更奇怪的。我相信它与上面的相同:


(l1, l2) -> {

    int cmp = l1.stream().findAny().flatMap(p1 -> l2.stream().findAny().map(

            p2 -> Integer.compare(p1.getPoints(), p2.getPoints()))).orElse(0);

    if (cmp < 0) l1.clear();

    if (cmp <= 0) l1.addAll(l2);

}


查看完整回答
反对 回复 2022-05-21
  • 3 回答
  • 0 关注
  • 133 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信