[英]Find average using java 8 streams
我是Java 8的新手,还处于学习阶段。 我必须使用java 8编写以下逻辑。我有一个Json数组数据,我的json结构如下所示。
{"list":[{"core":{"min":281.556,"max":286.67,"top":972.73},"dt":"2017-02-16 12:00:00"},{"core":{"min":281.821,"max":285.66,"top":970.91},"dt":"2017-02-16 15:00:00"},{"core":{"min":274.498,"max":277.05,"top":970.44},"dt":"2017-02-16 18:00:00"},{"core":{"min":271.503,"max":272.78,"top":969.32},"dt":"2017-02-16 21:00:00"}]}
这个jsonArray将包含大约100个jsonObject,每3小时有一个数据。 我实际上需要使用java 8流或使用其他java 8功能分别找到max的平均值和max的平均值。 另一个标准是最小和最大平均值应基于白天或夜晚。 如果dt包含06:00或09:00或12:00或15:00,则应为dayavg(白天的最小值+最大值),否则应为夜间平均值((夜间最小值+最大值))。 顶部不依赖于白天或黑夜。 任何帮助赞赏
下面是使用java 7的登录。需要使用Java 8功能。
int dayavg=0;
int nightavg = 0;
int topavg=0;
int day=0;
int night = 0;
int top=0;
for(int i=0;i<50;i++){
JsonNode node = list.get(i);
String dt = node.get("dt").textValue();
if(dt.contains("06:00:00")|| dt.contains("09:00:00") || dt.contains("12:00:00") || dt.contains("15:00:00")){
int val = node.get("core").get("min").asInt() + node.get("core").get("max").asInt();
day = day + val;
}
if(dt.contains("18:00:00")|| dt.contains("21:00:00") || dt.contains("00:00:00") || dt.contains("03:00:00")){
int val = node.get("core").get("min").asInt() + node.get("core").get("max").asInt();
night = night + val;
}
int val = node.get("core").get("top").asInt();
top = top + val;
}
topavg = top/50;
dayavg = day/100;
nightavg = night/100;
如果你想只有一个流,你可以做自己的收藏家
有两个POJO像这样:
class Values {
int top,day,night;
}
class Avg {
int topAvg,dayAvg,nightAvg;
}
收藏家将如下所示:
BinaryOperator<Values> combiner = (left,right) -> {
left.day+=right.day;
left.night+=right.night;
left.top+=right.top;
return left;
};
Function<Values,Avg> finisher =(value)->{
Avg avg = new Avg();
avg.topAvg = value.top/50;
avg.dayAvg = value.day/100;
avg.nightAvg = value.night/100;
return avg;
};
BiConsumer<Values,JsonNode> accumulator= (values, node) ->{
String dt = node.get("dt").textValue();
if(dt.contains("06:00:00")|| dt.contains("09:00:00") || dt.contains("12:00:00") || dt.contains("15:00:00")){
int val = node.get("core").get("min").asInt() + node.get("core").get("max").asInt();
values.day += val;
}
if(dt.contains("18:00:00")|| dt.contains("21:00:00") || dt.contains("00:00:00") || dt.contains("03:00:00")){
int val = node.get("core").get("min").asInt() + node.get("core").get("max").asInt();
values.night += val;
}
int val = node.get("core").get("top").asInt();
values.top += val;
};
Avg avg = list.stream()
.collect(Collector.of(Values::new, accumulator,combiner,finisher));
你也可以使用多个流,并为dayAvg提供类似的东西:
OptionalDouble dayAvg = list.stream()
.filter(node -> {
String dt = node.get("dt").textValue();
return dt.contains("06:00:00") || dt.contains("09:00:00") || dt.contains("12:00:00") || dt.contains("15:00:00");
})
.mapToInt(node -> node.get("core").get("min").asInt() + node.get("core").get("max").asInt())
.average();
我认为它更清楚,但它可能会降低该方法的性能
您可以使用自定义enum
:
static enum Type { DAY, NIGHT, TOP }
然后收集两次你的清单:
// Day and night
Map<Type, Double> result = list.stream()
.collect(
Collectors.groupingBy(node -> {
String dt = node.get("dt").textValue();
if(dt.contains("06:00:00")|| dt.contains("09:00:00") || dt.contains("12:00:00") || dt.contains("15:00:00")){
return Type.DAY;
}
if(dt.contains("18:00:00")|| dt.contains("21:00:00") || dt.contains("00:00:00") || dt.contains("03:00:00")){
return Type.NIGHT;
}
// Should not happen
return null;
},
Collectors.averagingInt(node -> node.get("core").get("min").asInt() + node.get("core").get("max").asInt()))
);
// Top
result.putAll(
list.stream().collect(
Collectors.groupingBy(node -> Type.TOP,
Collectors.averagingInt(node -> node.get("core").get("top").asInt()))
)
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.