Java 什么';修剪这组数据的简单方法是什么?(爪哇)
我正在练习用Java处理简单的JSON数据,我有点卡住了 假设我是一名面包师,我有多年来各种产品的数据。例如,我有三种产品:蛋糕、百吉饼和饼干。我的数据每年收集一次,因此示例JSON数据集可以是:Java 什么';修剪这组数据的简单方法是什么?(爪哇),java,json,class,arraylist,Java,Json,Class,Arraylist,我正在练习用Java处理简单的JSON数据,我有点卡住了 假设我是一名面包师,我有多年来各种产品的数据。例如,我有三种产品:蛋糕、百吉饼和饼干。我的数据每年收集一次,因此示例JSON数据集可以是: [ {"name": "cake", "consumers": 200, "tastiness": 8.0}, {"name": "cake", "consumers": 220, "tastiness": 8.3}, {"name": "bagel", "consumers": 1000, "tas
[ {"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} ]
正如你所看到的,有两个“蛋糕”条目表示蛋糕已经存在两年,三个“百吉饼”条目表示百吉饼已经存在三年,等等
我想压缩这些数据,得到每种产品的加权平均口感。例如,蛋糕的平均味道是(8.0*200+8.3*220)/(200+220)=8.157,因此我希望我的新集合除了面包圈和饼干的相应平均味道之外,还包含一个带值的数据条目(“蛋糕”,8.157)
解析JSON数据并提取我想要的值是很简单的,但我正在努力解决的是提取/压缩同名数据值并获得平均美味度的最佳方法
到目前为止,我已经考虑过为姓名、消费者编号和美味度制作ArrayList,但我意识到这可能有点混乱和不方便
我目前正在考虑创建一个名为“Product”的单独类,其属性为“name”、“consumers”和“Tasty”,然后创建一个arrayList
。然而,我一直在思考如何最好地遍历产品的arrayList,并获取具有相同名称的产品并计算加权平均值
我知道我的问题可能有一个非常简单的解决方案,但目前我还没有找到,所以我非常感谢您的帮助。谢谢:)因此,您有多种产品和任意数量的组,您需要处理 您是否考虑过使用
地图
?您可以使用类似于Map
您可以通过使用Java8流(流化列表
)并对产品名称进行分组来构建映射
最后,您可以在地图的键集
和列表中的产品列表
例如:
List products=buildProductsList();
Map productsGroupedByName=products.stream()
.collect(Collectors.groupingBy(Product::getName));
for(字符串名称:productsGroupedByName.keySet()){
System.out.println(“名称为:“+name”);
for(产品:productsGroupedByName.get(名称)){
//对产品做些什么
}
}
我认为您使用上述属性创建容器类的想法是个好主意
通过将java.util.stream.Collectors
类中的groupby
和reduce
组合在一起,您可以实现这一点
我们首先定义一个类来保存我们的数据:
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));
SugarStats
的总可口度得分,而不是单个条目的得分:
.map(t -> new SugarStats(t.getName(), t.getConsumers(), t.getConsumers() * t.getTastiness()))
例如,cookie sugarstats实例现在的味道是500*9.6=4800
映射
,其中名称
为键,而列表
包含所有值。然而,我们对列表不感兴趣,我们只对平均值感兴趣。所以我们提供了一个减少的下游收集器,它收集所有的SugarStats,并将它们结合起来,合计消费者数量和美味度
例如,newsugarstats(“cake”,2001600.0)+newsugarstats(“cake”,2201826.0)
将成为newsugarstats(“cake”,4203426)
result.values().stream()
.forEach(t -> System.out.println(t.getName() + ": " + t.getAverageTastiness()));
.您的“分组依据”来自哪里?它来自收集器软件包<代码>导入静态java.util.stream.Collectors.groupingBy代码>啊,好的,谢谢。对于每个循环的第一个循环,从productsGroupedByName中获取名称,我得到一个“只能迭代一个数组或java.lang.Iterable的实例”红色下划线,这很奇怪,因为映射不是Iterable吗?糟糕,我忘了向它添加键集。它应该读为(字符串名称:productsGroupedByName.keySet()),我也更新了我的答案。关于如何有效地获得味觉的加权平均值,有什么建议吗?既然我已经为每一种产品做了准备,那么我是否要检查每一种产品,并将消费者和美味度值存储到一个单独的列表中,直到名称发生变化,然后对我创建的每个列表分别执行加权平均数计算?还是有更好的办法?
.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()));