Java 什么';修剪这组数据的简单方法是什么?(爪哇)

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

我正在练习用Java处理简单的JSON数据,我有点卡住了

假设我是一名面包师,我有多年来各种产品的数据。例如,我有三种产品:蛋糕、百吉饼和饼干。我的数据每年收集一次,因此示例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} ]
正如你所看到的,有两个“蛋糕”条目表示蛋糕已经存在两年,三个“百吉饼”条目表示百吉饼已经存在三年,等等

我想压缩这些数据,得到每种产品的加权平均口感。例如,蛋糕的平均味道是(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()));