java - 有效地计算学生列表中给定指标的统计数据
问题描述
学生.java
public class Student{
/*
Metrics examples (out of 100):
mathScore:98
scienceScore:99
englishScore:92
*/
private Map<String, Double> metrics = new HashMap<>();
}
统计数据
public enum Statistic {
AVERAGE,
MIN,
MAX
}
结果
public class Result {
private Statistic statistic;
private double value;
private String metric;
}
构建可以根据学生列表上请求的指标执行请求的静态分析的引擎的最有效方法是什么
这是一个例子:
假设我有一份学生名单。
List<Student> students = [john, json, elliot, sarah, callie, matt, leigh]; //Assume each entry is an object
我也有我感兴趣的指标列表
List<String> metrics =["mathScore", "scienceScore"]; //Just an example. I can add additional metrics to this list or remove them.
以及我想要执行的统计数据
List<Statistic> stats = [MIN, MAX]; //Just an example. I can request additional operations if necessary.
这是需要有效构建的方法的签名
public List<Resut> calculate( List<String> requestedMetrics, List<Statistic> requestedStatistics, List<Student> students){
}
这是我最初的想法
- 将 requestedMetrics 和 requestedStatistics 转换为集合以消除重复项。
- 遍历每个指标。对于每个指标,遍历每个统计数据并计算它。有没有更好的办法?以及如何将实现分解为更小的功能等以获得更清洁的解决方案?
- 创建一个缓存(地图)怎么样,这样我们就不需要一次又一次地重新处理所有内容?
这是我当前的实现
@Component
public class StatisticalAnalysis {
@Override
public List<Result> calculate(List<Student> students, List<String> metrics, List<Statistic> stats) {
return analyze(new HashSet<>(students), new HashSet<>(metrics), new HashSet<>(stats));
}
public List<Result> analyze(HashSet<Student> students, HashSet<String> metrics, HashSet<Statistic> stats) {
List<Result> calculate = new ArrayList<>(metrics.size());
for (String metric : metrics) {
for (Statistic stat : stats) {
results.add(createResult(students, metric, stat ));
}
}
return results;
}
private Result createResult(HashSet<Student> students, String metric, Statistic stat) {
return new Result(metric, stat, calcStatValue(students, metric, stat));
}
private double calcStatValue(HashSet<Student> students, String metric, Statistic stat) {
List<Double> values = new ArrayList<Double>(students.size());
for(Student measurement: students){
Double value = measurement.getMetric(metric);
if(value!=null)
values.add(value);
}
return performStatOperation(stat, values);
}
private double performStatOperation(Statistic stat, List<Double> values) {
switch (stat) {
case MIN:
return Collections.min(values);
case MAX:
return Collections.max(values);
case AVERAGE:
return values.stream().mapToDouble(val -> val).average().orElse(0.0);
default:
throw new UnsupportedOperationException(String.format("Calculation of Statistic %s is currently unsupported", stat));
}
}
}
解决方案
这些指标可以是一个枚举而不是一个字符串,以便它们在一个地方定义并且可以在所有代码中轻松使用。
此外,如果学生在构建后没有被修改,他们的类已经可以包含一个可以使用的列表,而不是依赖于外部方法。唯一的计算是对等级进行排序以找到最小值和最大值,考虑到指标的简短列表,这是一个微不足道的构建开销。
否则,您可以缓存学生的结果列表,并在其指标被修改时将其标记为缓存失效。
推荐阅读
- python - 网页抓取 - HTTP 错误 403:禁止 - Ziprecruiter
- python - JSON数组到pyspark中的Dataframe
- javascript - 在不使用任何内置数组方法的情况下重新实现/重新创建 .concat 方法
- java - 如何通过 Spark WORKER 节点从 MySQL 读取数据?
- android - 视频结束后视频视图变黑且无法重播
- asp.net-core - 部署到 Server 2019 上的 IIS 时,asp.net 5 中的 ILogger 无法正常工作
- html - 创建一个漂亮的圆角桌
- c# - 当我更新我的 Nugets 时使用简单容器的 c# 问题
- go - 为什么 leveldb 错误仅出现在 10% 的测试运行中以及如何解决?
- c++ - 命名空间、包含、一个解决方案中的多个项目以及 cpp 中的模块的位置