Way*_*eio 5 java lambda java-8 java-stream
我正在尝试计算在“对象列表”中的字段中看到一个Int的次数。
这是我的代码
TreeMap<Integer, Double> ratings = new TreeMap();
ArrayList<Establishment> establishments = new ArrayList<>();
double one = 0;
double two = 0;
double three = 0;
double five = 0;
for (Establishment e : establishments) {
if (e.getRating() == 1) {
one++;
}
if (e.getRating() == 2) {
two++;
}
if (e.getRating() == 3) {
three++;
}
if (e.getRating() == 5) {
five++;
}
}
ratings.put(1, (one / establishments.size()) * 100);
ratings.put(2, (two / establishments.size()) * 100);
ratings.put(3, (three / establishments.size()) * 100);
ratings.put(5, (five / establishments.size()) * 100);
Run Code Online (Sandbox Code Playgroud)
但这并不理想,如果添加更多的评分(例如20+),则会创建大量的双打,并且无法维护。
我知道如果我有一个整数列表,我可以对Stream进行操作
listOfInts.stream().filter(i -> i == 3).count()
Run Code Online (Sandbox Code Playgroud)
但这是一个对象列表,其中包含一个int,我需要计算该对象列表中的评级数量==X。
所以我需要的伪代码:
Establishmentemnts.getAllRatings()。stream()。filter(ratings-> rating == 3).count()*
*对每种评级类型1-5重复
**没有getAllRatings-我想这就是我要解决的问题)
你可以做:
Map<Integer, Double> ratings = new TreeMap<>();
List<Establishment> establishments = new ArrayList<>();
establishments.stream()
.collect(Collectors.groupingBy(Establishment::getRating, Collectors.counting()))
.forEach((k, v) -> ratings.put(k, (double)v/establishments.size() * 100));
Run Code Online (Sandbox Code Playgroud)
Collectors::groupingBy
与配合使用Collectors::counting
,将创建一个Map
由评分计数组成的内容,然后将forEach
其添加到TreeMap
或者,按照VGR的建议,可以更优雅地使用Collectors::collectingAndThen
:
Map<Integer, Double> ratings =
establishments.stream()
.collect(
Collectors.groupingBy(Establishment::getRating,
Collectors.collectingAndThen(Collectors.counting(), c -> c * 100.0 / establishments.size())
));
Run Code Online (Sandbox Code Playgroud)
它将直接创建,Map
而无需创建Map
,再次对其进行流式处理,然后Map
再次收集
小智 5
仅使用或多或少的流:
List<Establishment> establishments = new ArrayList<>();
Map<Integer, Double> ratings = establishments.stream()
.collect(Collectors.groupingBy(Establishment::getRating, Collectors.counting()))
.entrySet()
.stream()
.collect(Collectors.toMap(e -> e.getKey(),
e -> 100.0 * (e.getValue() / establishments.size())));
Run Code Online (Sandbox Code Playgroud)
以下是如何使用流来实现 getAllRatings 来获取评级列表
List<Integer> attributes = establishments.stream().map(es -> es.getRating()).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
因此,要获取特定评级的评级计数,您可以使用
establishments.stream().map(es -> es.getRating()).collect(Collectors.toList()).stream().filter(ratings -> ratings == 3).count()
Run Code Online (Sandbox Code Playgroud)
如果您想获取所有评级的评级计数/百分比,请使用@Marek 的答案中的代码