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