当前位置: 首页 > 知识库问答 >
问题:

java 8中并行使用BigDecimal进行分组和求和

温翔宇
2023-03-14
Example:
[  
   {  
      "name":"Product A",
      "amount":"40.00",
      "description":"Info1",
      "number":"65"
   },
   {  
      "name":"Product A",
      "amount":"50.00",
      "description":"Info2",
      "number":"67"
   },
   {  
      "name":"Product A",
      "amount":"100.00",
      "description":"Info3",
      "number":"87"
   },
   {  
      "name":"Product B",
      "amount":"45.00",
      "description":"Info4",
      "number":"86"
   },
   {  
      "name":"Product D",
      "amount":"459.00",
      "description":"Info5",
      "number":"7"
   },
   {  
      "name":"Product B",
      "amount":"50.00",
      "description":"Info6",
      "number":"8"
   }
]
{  
   "Product A = 190.00":[  
      {  
         "name":"Product A",
         "amount":"40.00",
         "description":"Info1",
         "number":"65"
      },
      {  
         "name":"Product A",
         "amount":"50.00",
         "description":"Info2",
         "number":"67"
      },
      {  
         "name":"Product A",
         "amount":"100.00",
         "description":"Info3",
         "number":"87"
      }
   ],
   "Product B=95.00":[  
      {  
         "name":"Product B",
         "amount":"45.00",
         "description":"Info4",
         "number":"86"
      },
      {  
         "name":"Product B",
         "amount":"50.00",
         "description":"Info6",
         "number":"8"
      }
   ],
   "Product D = 459.00":[  
      {  
         "name":"Product D",
         "amount":"459.00",
         "description":"Info5",
         "number":"7"
      }
   ]

我已经创建了一个beanProductBean,其中包含所有字段(name、amount、description和number),以及相同的getter和setter。productBeans有所有产品的列表。

Map<String, List<ProductBean>> groupByProduct = 
               productBeans.stream()
                     .collect(Collectors.groupingBy(item -> item.getName()))

Map<String, BigDecimal> result = 
      productBeans.stream()
             .collect(Collectors.groupingBy(ProductBean::getName, 
                                Collectors.mapping(ProductBean::getAmount, 
                     Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));

groupByProduct具有用名称分组的产品列表。结果给出了以产品地图为关键,以产品总量为价值的产品地图。

但在这里,我试图将产品和总金额映射到产品列表中。我试图结合上面的代码来获得预期的输出,但未能实现。通过遍历映射也实现了同样的效果。

但是,任何关于合并上述代码以获得映射的帮助,其中产品名称和金额作为键,列表作为值都是有帮助的。

共有1个答案

柯锋
2023-03-14

您似乎想要映射 > ,其中字符串表示名称BigDecimal是所有产品数量的总和,list 是该特定组中的产品列表。

这样的地图是不可能的,因此,您已经设法分两个步骤来完成它,这不是非常有效的,它没有将相关的数据放在一起,而是将其分成两个地图。

我的建议是创建一个这样的包装类:

class ResultSet {

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }

    public List<ProductBean> getProductBeans() {
        return productBeans;
    }

    public void setProductBeans(List<ProductBean> productBeans) {
        this.productBeans = productBeans;
    }

    private String name;
    private BigDecimal amount;
    private List<ProductBean> productBeans;

    @Override
    public String toString() {
        return "ResultSet{" +
                "name='" + name + '\'' +
                ", amount=" + amount +
                ", productBeans=" + productBeans +
                '}';
    }
}

现在,您可以通过以下方式完成手头的任务:

List<ResultSet> result = productList.stream()
                .collect(Collectors.groupingBy(ProductBean::getName))
                .entrySet()
                .stream()
                .map(e -> {
                    ResultSet resultSet = new ResultSet();
                    BigDecimal sum = e.getValue().stream()
                            .map(ProductBean::getAmount)
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    resultSet.setName(e.getKey());
                    resultSet.setAmount(sum);
                    resultSet.setProductBeans(e.getValue());
                    return resultSet;
                }).collect(Collectors.toList());

这将根据ProductBean名称进行分组,然后将每个组映射到ResultSet实例,该实例将封装名称、特定组中数量的总和以及组中整个ProductBean

您可以通过为映射创建一个方法来进一步重构上述流查询:

private static ResultSet mapToResultSet(Map.Entry<String, List<ProductBean>> e) {
        ResultSet resultSet = new ResultSet();
        BigDecimal sum = e.getValue().stream()
                .map(ProductBean::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        resultSet.setName(e.getKey());
        resultSet.setAmount(sum);
        resultSet.setProductBeans(e.getValue());
        return resultSet;
}
List<ResultSet> result = productList.stream()
                .collect(Collectors.groupingBy(ProductBean::getName))
                .entrySet()
                .stream()
                .map(Main::mapToResultSet) // Main representing the class containing the mapToResultSet method
                .collect(Collectors.toList());
 类似资料:
  • 我正在使用我有一个类,如下所示: 现在我想做的是: 筛选出senderId无效的记录(使用映射) 下面是我的代码: 这给我带来了一个错误: 错误:(105,90)java:找不到适用于groupingBy(共享[…]的方法gMode,java。util。作用函数)方法java。util。流动收藏家。groupingBy(java.util.function.function)不适用(无法推断类型变

  • 本文向大家介绍Java8 stream 中利用 groupingBy 进行多字段分组求和案例,包括了Java8 stream 中利用 groupingBy 进行多字段分组求和案例的使用技巧和注意事项,需要的朋友参考一下 Java8的groupingBy实现集合的分组,类似Mysql的group by分组功能,注意得到的是一个map 对集合按照单个属性分组、分组计数、排序 集合按照多个属性分组 1.

  • 我可以同时使用和吗?

  • 问题内容: 我来自拥有LINQ的.NET世界,因此我可以像在SQL中通常看到的那样进行内存中查询。 我要对该结构进行切片,希望将其按8个字段分组,然后对另一个整数字段求和。就像是: 我以为: 创建一个Equal函数,以比较结构(那八个字 段)。遍历我正在分析的集合。对于每个项目, 检查它是否已经在哈希表中。如果存在=>我对字段求和。如果不是=>我将新项目添加到哈希表。 有没有更好的方法或任何美观,

  • 我有课 给出一个Person类列表,我根据该类的不同属性进行聚合。对于(如)- 现在我需要得到一个结果,这样我就应该根据国家和城市的组合得到总的“totalcountrytoCityCount”,并且根据国家、城市和宠物的组合得到总的“petCount”。我可以使用groupingBy和summingint分别获得它们 它给出了结果 但我想要的实际结果是:- 令人惊讶地删除了计数

  • 我有桌子: 类别 和餐桌产品: 我要选择category,sum(quantity) //(产品的所有数量都属于category和category.parent_id=null) 结果: 如何使用sql查询(或rails)可以达到上述效果。TKS.