我正在练习使用 Java 中的简单 JSON 数据,但遇到了一些困难。
假设我是一名面包师,我有一些多年来我的各种产品的数据。例如,我有三种产品:蛋糕、百吉饼和 cookies 。我的数据每年收集一次,因此 JSON 数据集示例可能类似于:
[ {"name": "cake", "consumers": 200, "tastiness": 8.0}, {"name": "cake", "consumers": 220, "tastiness": 8.3}, {"name": "bagel", "consumers": 1000, "tastiness": 6.4}, {"name": "bagel", "consumers": 1200, "tastiness": 7.5}, {"name": "bagel", "consumers": 800, "tastiness": 5.7}, {"name": "cookie", "consumers": 500, "tastiness": 9.6} ]
正如您所看到的,有两个“cake”条目表示蛋糕已存在两年,三个“bagel”条目表示百吉饼已存在三年,等等。
我想压缩这些数据以获得每种产品的加权平均味道。例如,蛋糕的平均味道是 (8.0*200 + 8.3*220)/(200+220) = 8.157,所以我希望我的新集合包含一个值为 ("cake", 8.157) 的数据条目,除了百吉饼和 cookies 相应的平均美味之外。
解析 JSON 数据并提取我想要的值是微不足道的,但我正在努力的是提取/压缩具有相同名称的数据值并获得平均味道的最佳方法。
到目前为止,我已经考虑过为名称、consumerNumbers 和 tastiness 创建 arrayList,但我意识到这可能有点困惑和不方便。
我目前正在考虑创建一个名为“Product”的单独类,其属性为“name”、“consumers”和“tastiness”,然后创建一个单个 arrayList<Product>
。但是,我坚持如何最好地迭代产品的 arrayList 并获取具有相同名称的产品并计算加权平均值。
我知道可能存在一个非常简单的解决方案来解决我的问题,但目前我还没有找到它,所以任何帮助将不胜感激。谢谢:)
最佳答案
我认为您创建具有上述属性的容器类的想法是个好主意。
与 groupingBy
的组合和reducing
来自java.util.stream.Collectors
类,你可以实现这个。
我们首先定义一个类来保存我们的数据:
public class SugarStats {
private String name;
private long consumers;
private double tastiness;
// Constructor(name, consumers, tastiness) and getters left out for brevity
}
我们将使用这个容器类来计算平均值,因此我们将添加一个方法:
public double getAverageTastiness() {
return this.tastiness / this.consumers;
}
此外,我假设已经完成从 JSON 到 POJO 的转换,并且您的数据如下所示:
List<SugarStats> stats = Arrays.asList(
new SugarStats("cake", 200, 8.0),
new SugarStats("cake", 220, 8.3),
new SugarStats("bagel", 1000, 6.4),
new SugarStats("bagel", 1200, 7.5),
new SugarStats("bagel", 800, 5.7),
new SugarStats("cookie", 500, 9.6));
然后我们将执行以下操作:
我们将流式传输列表:
stats.stream()
然后我们将总结每个
SugarStats
的总美味分数。 ,而不是单个条目的分数:.map(t -> new SugarStats(t.getName(), t.getConsumers(), t.getConsumers() * t.getTastiness()))
例如,cookie Sugarstats 实例现在的味道为
500 * 9.6 = 4800
.然后我们收集结果,按名称分组。这通常会返回
Map
与name
作为 key 和List<SugarStats>
与所有值(value)观。但是,我们对List
不感兴趣。 ,我们只对平均值感兴趣。因此,我们提供了一个减少下游收集器,它收集所有 SugarStats 并将它们组合起来,计算出消费者数量和味道的总数。例如,
new SugarStats("cake", 200, 1600.0) + new SugarStats("cake", 220, 1826.0)
将变成new SugarStats("cake", 420, 3426)
..collect(groupingBy(t -> t.getName(), reducing( new SugarStats("", 0, 0), (p1, p2) -> new SugarStats( p2.getName(), p1.getConsumers() + p2.getConsumers(), p1.getTastiness() + p2.getTastiness() ) ) ));
现在我们可以品尝到美味了:
result.values().stream()
.forEach(t -> System.out.println(t.getName() + ": " + t.getAverageTastiness()));
关于java - 修剪这组数据的简单方法是什么? ( java ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57897008/