我正在写一种简单的方法来打印一系列游戏结果的统计数据。每个游戏都有一个结果列表,其中包含根据游戏结果列出的枚举。 我的老师在我的代码中注释了一个待办事项:
public static void printStatistics(List<Game> games) {
float win = 0;
float lose = 0;
float draw = 0;
float all = 0;
//TODO: should be implemented /w stream API
for (Game g : games) {
for (Outcome o : g.getOutcomes()) {
if (o.equals(Outcome.WIN)) {
win++;
all++;
} else if (o.equals(Outcome.LOSE)) {
lose++;
all++;
} else {
draw++;
all++;
}
}
}
DecimalFormat statFormat = new DecimalFormat("##.##");
System.out.println("Statistics: The team won: " + statFormat.format(win * 100 / all) + " %, lost " + statFormat.format(lose * 100 / all)
+ " %, draw: " + statFormat.format(draw * 100 / all) + " %");
}
我熟悉lambda表达式。我尝试在网上寻找解决方案,但找不到流访问类的字段的示例。如果您可以给我解决方案,或者提供相关的教程,我将非常高兴。谢谢。
答案 0 :(得分:5)
您可以将游戏,flatMap流化为结果,然后将它们收集到计数图中:
Map<Outcome, Long> counts = games.stream()
.map(Game::getOutcomes)
.flatMap(Collection::stream)
.collecting(Collectors.groupingBy(o -> o, Collectors.counting()));
long win = counts.getOrDefault(Outcome.WIN, 0L);
long lose = counts.getOrDefault(Outcome.LOSE, 0L);
long draw = counts.getOrDefault(Outcome.DRAW, 0L);
long all = games.stream()
.mapToInt(g -> g.getOutcomes().size())
.sum();
答案 1 :(得分:2)
groupingBy
适合这种情况:
Map<Outcome, Long> map = games.stream()
.flatMap(game -> game.getOutcomes().stream())
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
并获得win
,lose
个计数:
long win = map.get(Outcomes.WIN);
long lose = map.get(Outcomes.LOSE);
...
要获得all
个计数,您需要对地图中的所有值求和
long all = map.values().stream()
.mapToLong(Long::valueOf)
.sum();
答案 2 :(得分:0)
要访问Stream
中的类的字段,请使用map
:
games.stream().map(game ->
game.getOutcomes().stream().map(outcome -> {
// do something with each `outcome`
})
)
上面的代码假定getOutcomes()
返回List
,这在OP的当前版本中未指定。
请注意,您不能像您希望的那样简单地在Stream
中增加计数器,因为Stream
中使用的所有变量必须是最终变量或有效地是最终变量。您必须对Stream
API进行更多的研究,才能弄清楚如何增加您在原始解决方案中的操作方式。
提示:您想做类似this的事情,它利用了Collectors.groupingBy()。