【问题标题】:How to obtain a list after sum over similar elements如何在对相似元素求和后获得列表
【发布时间】:2021-04-18 23:45:44
【问题描述】:

我有一个 Products 类列表,它具有以下属性:

public class Products{
private int month;
private int year;
private int sku;
private String detail;
private Double quantity;
private Double price;
private Double discount;
private Double %discount;

    // getters and setters

static List<Products> sumProduct(List<Products> itemList) {
    
List<Product> tempListP = new ArrayList<Product>();

    Collections.sort(itemList, Comparator.comparing(Product::getYear)
            .thenComparing(Product::getMonth).thenComparing(Product::getSku));
    
    
    Integer itemCode = null; 
    double quantiti = 0;
    double price = 0;
    double discount = 0;
    double %discount = 0;
    Products itemObj = null;
    Integer itemMonth= null;
    Integer itemYear= null;
    
        for (int i = 0; i < itemList.size(); i++) {
            if (itemCode == null || (itemCode.equals(itemList.get(i).getSku())  && itemMonth.equals(itemList.get(i).getMonth()) && itemMonth.equals(itemList.get(i).getYear())  )) {
                quantiti = quantiti + itemList.get(i).getquantiti();
                price = price + itemList.get(i).getprice();
                discount = discount + itemList.get(i).getdiscount();
                %discount = %discount + itemList.get(i).get%discount();
                itemMonth = itemList.get(i).getMonth();
                itemYea = itemList.get(i).getYear();
            } else {
                
                itemObj = new Product( itemList.get(i).getMonth(), itemList.get(i).getYear(), itemCode, "" , quantiti, price,discount,%discount);
                
                
                if (tempListP.contains(itemObj)) {
                    tempListP.remove(itemObj);
                }
                tempListP.add(itemObj);
                quantiti = 0;
                quantiti = quantiti + itemList.get(i).getquantiti();
                price = 0;
                price = price + itemList.get(i).getprice();
                discount = 0;
                discount = discount + itemList.get(i).getdiscount();
                %discount = 0;
                %discount = %discount + itemList.get(i).get%discount();
                itemMonth = itemList.get(i).getMonth();
                itemYea = itemList.get(i).getYear();
            }

            itemCode = itemList.get(i).getSku();

            if (i == itemList.size() - 1) {
                itemObj = new Product( itemList.get(i).getMonth(), itemList.get(i).getYear(), itemCode, "" , quantiti, price,discount,%discount);
                tempListP.add(itemObj);
            }
        
        
    }
    

    return itemList;
}


}

主要

public static void main(String[] args) {

   List<Products> items = new ArrayList<Products>();

   items.add(new Products(8,2020,10203040,"Tshirt",1,10.00,1.00,0.1));
   items.add(new Products(9,2020,10203040,"Tshirt",2,20.00,2.00,0.2));
   items.add(new Products(3,2021,10203040,"Tshirt",3,30.00,3.00,0.3));
   items.add(new Products(7,2020,50607080,"Tshirt",4,40.00,4.00,0.4));
   items.add(new Products(8,2020,10203040,"Tshirt",5,50.00,5.00,0.5));
   items.add(new Products(8,2021,10203040,"Tshirt",8,80.00,8.00,0.8));

  Products.sumProduct(items);

输入

Month | Year | Sku | Detail | Quantity | Price | Discount | % Discount

8 | 2020 | 10203040 | Tshirt | 1 | 10 | 1 | 0.1

9 | 2020 | 10203040 | Tshirt | 2 | 20 | 2 | 0.2

3 | 2021 | 10203040 | Tshirt | 3 | 30 | 3 | 0.3

7 | 2020 | 50607080 | Tshirt | 4 | 40 | 4 | 0.4

8 | 2020 | 10203040 | Tshirt | 5 | 50 | 5 | 0.5

8 | 2021 | 10203040 | Tshirt | 8 | 80 | 8 | 0.8

最终的结果应该是这样的:

输出:

Month | Year | Sku | Detail | Quantity | Price | Discount | % Discount

7 | 2020 | 50607080 | Tshirt | 4 | 40 | 4 | 0.4

8 | 2020 | 10203040 | Tshirt | 6 | 60 | 6 | 0.6

9 | 2020 | 10203040 | Tshirt | 2 | 20 | 2 | 0.2

3 | 2021 | 10203040 | Tshirt | 3 | 30 | 3 | 0.3

8 | 2021 | 10203040 | Tshirt | 8 | 80 | 8 | 0.8

我想创建一个函数,它遍历产品列表并对具有相同月份、年份和 sku 的项目的值求和,并返回数量、价格、折扣、%discount 的总和列表。

但是我如何将上面的代码链接起来计数和求和?特别是对于超过 3 个字段(月、年和 sku)的分组。有没有更好的方法来做到这一点?

真的,我需要帮助来对值求和,而不仅仅是对列表中的元素进行分组。

提前感谢您的帮助。

【问题讨论】:

    标签: java list arraylist collections


    【解决方案1】:

    如果您想在单个返回值中返回这些统计信息,理想情况下您应该拥有包含其中值的结构。这是一个更好的设计,可以重用产品类来包含聚合。那是以一种会让读者感到困惑的方式重载类的使用。

    这是记录的一个很好的用例,因为它们为您做了很多工作(例如,为您的排序和聚合定义 equalshashCode)。您可以添加一些方便的函数以使排序更容易:

    record MonthSKU(int month, int year, int sku) {
        MonthSKU(Product product) {
            this(product.month, product.year, product.sku);
        }
    }
    
    record ProductStats(double quantity, double price, double discount) {
        static ProductStats ZERO = new ProductStats(0, 0, 0);
        ProductStats(Product product) {
            this(product.quantity, product.price, product.discount);
        }
        ProductStats combine(ProductStats other) {
            return new ProductStats(quantity + other.quantity, price + other.price, discount + other.discount);
        }
    }
    

    现在使用流运算符进行分组和求和非常简单:

    Map<MonthSKU,ProductStats> stats = productList.stream()
        .collect(groupingBy(MonthSKU::new, 
            reducing(ProductStats.ZERO, ProductStats::new, ProductStats::combine));
    

    在我看来,与包含聚合值的产品列表和需要排序列表的算法相比,这是一个更易于理解的输出统计模型 - 这既难以理解又容易破解。

    此模型也更容易扩展以添加新字段或更复杂的统计信息(例如维护计数以计算平均值)。只需更改 2 条记录即可完成所有这些更改,而无需更改分组和归约操作。

    类似地,“详细信息”字段似乎包含与 sku 相关的信息,而不是与产品相关的信息。如果是这样,您应该将它们放在单独的 Map&lt;Integer,String&gt; 或专用的 SKU 类中。如果不是,那么当产品具有相同的 sku 但不同的详细信息时,您需要确定在汇总摘要中打印的内容。

    【讨论】:

      【解决方案2】:

      这个解决方案应该可以工作,我写了一个比较器来对产品进行排序。然后,如果连续的项目共享相同的值,则将必要的值相加。

      比较器

      public class ProductsComparator implements Comparator<Products> {
          public int compare(Products p1, Products p2) {
              int value1 = p1.year.compareTo(p2.year);
              if (value1 == 0) {
                  int value2 = p1.month.compareTo(p2.month);
                  if (value2 == 0) {
                      return p1.sku.compareTo(p2.sku);
                  } else {
                      return value2;
                  }
              }
              return value1;
          }
      }
      

      求和函数

      public static List<Products> sumProducts(List<Products> itemList) {
          List<Product> newList = new ArrayList<Product>();
          int index = -1;
      
          Collections.sort(itemList, new ProductsComparator());
           
          for(Products item : itemList){
              if(newList.size() != 0 && newList.get(index).getYear() == item.getYear() && newList.get(index).getMonth() == item.getMonth() && newList.get(index).getSku() == item.getSku()){
                   // Add values
                   newList.get(index).setquantiti(newList.get(index).getquantiti() +  item.getquantiti());
                   newList.get(index).setprice(newList.get(index).getprice() +  item.getprice());
                   newList.get(index).setdiscount(newList.get(index).getdiscount() +  item.getdiscount());
                   newList.get(index).set%discount(newList.get(index).get%discount() +  item.get%discount());
              }else{
                   newList.add(item);
                   index++;
              }
          }
      
          return newList;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-12
        • 2018-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-01
        • 1970-01-01
        相关资源
        最近更新 更多