Java 在具有流的列表中收集具有最大值的对象

Java 在具有流的列表中收集具有最大值的对象,java,java-stream,Java,Java Stream,我几乎完成了大学的扑克项目,但我仍然在努力学习java流。 我写了一个HandEvaluator类,它计算每个玩家手的力量,并将其分配给玩家。现在,我尝试将手牌得分最高的一个或多个玩家(如果有多个玩家拥有相同的分数/分罐)添加到一个列表中,以计算赢家 我对streams的语法有问题。我正在尝试这样的事情: playerList.stream().max(Comparator.comparing(Player::getHandScore)).get(); List<Player> t

我几乎完成了大学的扑克项目,但我仍然在努力学习java流。 我写了一个HandEvaluator类,它计算每个玩家手的力量,并将其分配给玩家。现在,我尝试将手牌得分最高的一个或多个玩家(如果有多个玩家拥有相同的分数/分罐)添加到一个列表中,以计算赢家

我对streams的语法有问题。我正在尝试这样的事情:

playerList.stream().max(Comparator.comparing(Player::getHandScore)).get();
List<Player> topScore = playersStream().collect(
    topGroup(Comparator.comparingInt(Player::getHandScore))
);
static <T> Collector<T, ?, List<T>> topGroup(final Comparator<? super T> comparator) {
    Objects.requireNonNull(comparator, "comparator");
    return Collector.of(
        () -> new Group<>(comparator),
        // My local compiler can't infer type properly, I had to help it.
        // Your experience may be different
        (BiConsumer<Group<T>, T>) Group::accept,
        Group::merge,
        Group::asList
   );
}

这是返回得分最高的玩家,但是如果有多个玩家得分相同怎么办?如何将它们添加到列表中?

一个简单易懂的解决方案如下:

int maxHighScore = playerList.stream()
                             .map(player -> player.getHandScore())
                             .max()
                             .orElse(-1);

List<Player> highestHandScores = playerList.stream()
                                           .filter(player -> player.getHandScore() == maxHighScore)
                                           .collect(Collectors.toList());
int maxHighScore=playerList.stream()
.map(player->player.getHandScore())
.max()
.orElse(-1);
List highestHandScores=playerList.stream()
.filter(player->player.getHandScore()==maxHighScore)
.collect(Collectors.toList());

在第一步中,我们得到maxHighScore,在第二步中,我们过滤球员,只保留得分最高的球员。

我做了类似的事情。我根据分数分组,然后找到具有最大关键值的分数。它将返回
Map.Entry的
可选
。它包含最大值和拥有它的玩家。然后我可以使用
getValue()
方法获得玩家列表

List value=playerList.stream()
.collect(分组依据(玩家::获取分数))
.entrySet()
.stream()
.max(Comparator.comparing(Map.Entry::getKey))
.get()
.getValue();
int max=playerList.stream()
.max(比较器比较(播放器::getHandScore))
.get()
.getHandScore();
列表播放列表=播放列表
.stream()
.filter(m->m.getHandScore()==max)
.collect(Collectors.toList());

其他一些答案的问题是,它们会遍历玩家列表两次——一次是按玩家分数分组,另一次是获取得分最高的玩家。在正常情况下,这可能是微不足道的,但当玩家列表较大时,这可能是一个问题

为了避免遍历列表两次,需要做的一件事是使用
SortedMap
。一旦我们根据球员的得分对他们进行分组,我们只需调用
lastKey()
即可立即获得最高的关键点:

SortedMap<Integer, List<Player>> topPlayers = playerList.stream()
    .collect(Collectors.groupingBy(Player::getScore, TreeMap::new, Collectors.toList()));
topPlayers.get(topPlayers.lastKey());

但是,在我看来,链接帖子的链接更好,因为并不是所有元素都被存储(分组到bucket中),而是如果发现它们不属于最大值,就会立即删除它们


这可能会节省内存。

我的答案将是一个带有
SortedMap
的版本,但此版本将在找到得分较高的单个玩家后立即丢弃“较低”组。此版本适用于元素非常多的情况,保留所有可见元素可能会成为一个问题。例如,当从一个非常大的文件中读取流项目时,该文件将无法放入内存中

整个解决方案如下所示:

playerList.stream().max(Comparator.comparing(Player::getHandScore)).get();
List<Player> topScore = playersStream().collect(
    topGroup(Comparator.comparingInt(Player::getHandScore))
);
static <T> Collector<T, ?, List<T>> topGroup(final Comparator<? super T> comparator) {
    Objects.requireNonNull(comparator, "comparator");
    return Collector.of(
        () -> new Group<>(comparator),
        // My local compiler can't infer type properly, I had to help it.
        // Your experience may be different
        (BiConsumer<Group<T>, T>) Group::accept,
        Group::merge,
        Group::asList
   );
}
List topScore=playerstream()。收集(
topGroup(Comparator.comparingInt(播放器::getHandScore))
);
要使其工作,您需要一个带有状态容器的自定义收集器来保存组。我不确定JDK中是否有类似的东西(在任何情况下都不在8中),但您可能可以在其中一个库中找到它。朝外的metod将如下所示:

playerList.stream().max(Comparator.comparing(Player::getHandScore)).get();
List<Player> topScore = playersStream().collect(
    topGroup(Comparator.comparingInt(Player::getHandScore))
);
static <T> Collector<T, ?, List<T>> topGroup(final Comparator<? super T> comparator) {
    Objects.requireNonNull(comparator, "comparator");
    return Collector.of(
        () -> new Group<>(comparator),
        // My local compiler can't infer type properly, I had to help it.
        // Your experience may be different
        (BiConsumer<Group<T>, T>) Group::accept,
        Group::merge,
        Group::asList
   );
}
静态收集器topGroup(最终比较器
topPlayers.get(topPlayers.lastKey());
执行不必要的映射查找。将
topPlayers
的类型更改为
NavigableMap
时,可以改用
topPlayers.lastEntry().getValue();