Java7/Java 8产品每日销量汇总

问题描述 投票:0回答:1

我有产品清单。我想对具有相同 id 的所有数据求和

public class Product {
    private int id;
    private String name;
    private double price;
    private int quantity;
.....
}

我将数据添加到列表中

List<Product> products = new ArrayList<>();
        products.add(new Product(1, "x", 100, 4));
        products.add(new Product(4, "y", 200, 2));
        products.add(new Product(4, "y", 50, 5));
        products.add(new Product(8, "k", 50, 1));
        products.add(new Product(10, "m", 1000, 1));
        products.add(new Product(1, "x", 100, 1));

到目前为止,我已经尝试过

Map<Integer, Double> productsByNameCategoryType = products.stream()
                .collect(Collectors.groupingBy(Product::getId,
                        Collectors.collectingAndThen(
                          Collectors.summarizingDouble(Product::getPrice),
                                p -> p.getSum())
                ));

这离我的期望太远了还在尝试中 我对输出的期望是

1、x、200、5

4, y, 250, 7

8、k、50、1

10、米、1000、1

java java-8
1个回答
0
投票

“...我有产品列表。我想对具有相同 id 的所有数据求和...”

创建一个新的 List 以包含合并的 Product 值。
遍历 products,然后从 i + 1 开始子遍历剩余条目。
合并 Product 值,然后添加到新的 List(如果它尚未包含 id)。

List<Product> l = new ArrayList<>();
Product p, t;
int i, j, k, n = products.size(), m;
boolean b;
for (i = 0; i < n; i++) {
    p = products.get(i);
    for (j = i + 1; j < n; j++)
        if (p.getId() == (t = products.get(j)).getId()) {
            p.setPrice(p.getPrice() + t.getPrice());
            p.setQuantity(p.getQuantity() + t.getQuantity());
        }
    b = false;
    for (k = 0, m = l.size(); k < m; k++)
        if (l.get(k).getId() == p.getId()) {
            b = true;
            break;
        }
    if (!b) l.add(p);
}

为了简化流程,请提供方法来合并值。

class Product {
    ...
    void merge(Product p) {
        price += p.getPrice();
        quantity += p.getQuantity();
    }
    ...
}
for (j = i + 1; j < n; j++)
    if (p.getId() == (t = products.get(j)).getId())
        p.merge(t);

或者,封装 ArrayList 类,并实现 merge 方法。

class ProductList extends ArrayList<Product> {
    @Override
    public boolean add(Product product) {
        return merge(product);
    }

    boolean merge(Product p) {
        for (Product v : this)
            if (p.getId() == v.getId()) {
                v.setPrice(p.getPrice() + v.getPrice());
                v.setQuantity(p.getQuantity() + v.getQuantity());
                return true;
            }
        return super.add(p);
    }
}
ProductList products = new ProductList();
products.add(new Product(1, "x", 100, 4));
products.add(new Product(4, "y", 200, 2));
products.add(new Product(4, "y", 50, 5));
products.add(new Product(8, "k", 50, 1));
products.add(new Product(10, "m", 1000, 1));
products.add(new Product(1, "x", 100, 1));

输出

1, x, 200.0, 5
4, y, 250.0, 7
8, k, 50.0, 1
10, m, 1000.0, 1

如果您确实想使用 stream,请使用 Collectors#toMap 方法。
并且,通过 collectingAndThen 方法填充 ArrayList 实例;这是一个有点不直观的步骤。

List<Product> l
    = products.stream()
              .collect(
                  Collectors.collectingAndThen(
                      Collectors.toMap(
                          Product::getId,
                          x -> x,
                          (a, b) -> {
                              Product p = new Product();
                              p.merge(b);
                              return p;
                          }),
                      x -> new ArrayList<>(x.values())));
© www.soinside.com 2019 - 2024. All rights reserved.