我正在尝试做一些练习,但我不想使用 if 语句,因为程序会太长。我有一个人员名单,其中:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private String name;
private Integer score;
private Group team;
private boolean active;
}
和
public enum Group {
G1, G2, G3
}
我的工作是找到一个人得分最高的组,但如果两个组的得分相同,我必须返回有更多不活跃人员的组。如果 inActive 玩家数量相同,我返回哪个组并不重要。
我将所有内容分组到地图中
Map<Group, List<Person>> collect = people.stream()
.collect(Collectors.groupingBy(Person::getTeam));
然后创建另外两个地图,我将分数和活跃人员分组。
for (Map.Entry<Group, List<Person>> entry : collect.entrySet()) {
collect1.put(entry
.getKey(), entry.getValue().stream()
.mapToInt(Person::getScore).sum());
collect2.put(entry.getKey(), entry.getValue().stream()
.filter(p -> !p.isActive())
.count());
}
我现在如何比较才能获得像任务中那样的结果。
我不会将聚合存储在两个单独的映射中,而是选择对聚合结果进行分组的对象。类似的东西
class GroupStats {
private Group group;
private int score;
private int activePlayers;
}
为了简洁起见,我在这里省略了构造函数和 getter。然后你可以做类似的事情
collect.entrySet().stream().map(e -> {
Group group = e.getKey();
int score = e.getValue().stream()
.mapToInt(Person::getScore).sum();
long activeCount = e.getValue().stream()
.filter(p -> p.isActive())
.count();
return new GroupStats(group, score, activeCount);
}).max(Comparator
.comparingInt(GroupStats::getScore)
.thenComparingLong(GroupStats::getActivePlayerCount))
.ifPresent(stats -> System.out.println(stats.group));
Comparator<List<Person>> groupComparator = Comparator
.<List<Person>, Integer>comparing(l -> l.stream()
.map(Person::getScore)
.max(Comparator.naturalOrder()).orElseThrow())
.thenComparing(l -> l.stream().filter(p -> !p.isActive()).count());
Map<Group, List<Person>> grouped =
people.stream().collect(Collectors.groupingBy(Person::getTeam));
Group max = grouped.values().stream().max(groupComparator).orElseThrow()
.getFirst().getTeam();
这会根据人员的
team
值(Group
)对人员进行分组,然后使用比较器来比较每组中的人员列表,该比较器首先检查组中的最高分数,然后检查组中不活跃的人数。组。