小能豆

Summarizing daily sales of products in Java7 / Java 8

javascript

I have list of products. I want to sum all the data with the same id

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

I added the data into a list

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));

So far, I have tried to

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

This is too far from my expectation and still trying on it My expectation of the output is

1, x, 200, 5

4, y, 250, 7

8, k, 50, 1

10, m, 1000, 1


阅读 78

收藏
2023-11-21

共1个答案

小能豆

You’re on the right track using the groupingBy collector. However, instead of using summarizingDouble, you can use reducing to perform the sum of prices and quantities for each group. Here’s an example of how you can achieve your expected output:

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Product> products = List.of(
                new Product(1, "x", 100, 4),
                new Product(4, "y", 200, 2),
                new Product(4, "y", 50, 5),
                new Product(8, "k", 50, 1),
                new Product(10, "m", 1000, 1),
                new Product(1, "x", 100, 1)
        );

        Map<Integer, Product> sumById = products.stream()
                .collect(Collectors.groupingBy(
                        Product::getId,
                        Collectors.reducing(new Product(0, "", 0, 0),
                                (p1, p2) -> new Product(
                                        p1.getId(),
                                        p1.getName(),
                                        p1.getPrice() + p2.getPrice(),
                                        p1.getQuantity() + p2.getQuantity())
                        )
                ));

        sumById.values().forEach(product ->
                System.out.println(product.getId() + ", " + product.getName() + ", " + product.getPrice() + ", " + product.getQuantity())
        );
    }
}

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

    public Product(int id, String name, double price, int quantity) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.quantity = quantity;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public int getQuantity() {
        return quantity;
    }
}

This code uses the groupingBy collector with a downstream reducing collector to sum the prices and quantities for each group of products with the same ID. The result is a map where the key is the ID, and the value is a Product object representing the sum of prices and quantities for that ID.

2023-11-21