Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

418
Visualizações
Java Stream group by 02 fields and aggregate by sum on 2 BigDecimal fields

Need help for a case on Stream with groupingBy I would like to be able to group by 2 different fields and have the sum of other BigDecimal fields, according to the different groupings. Here is my entity :

    public class Customer {
        private String name;
        private String type;
        private BigDecimal total;
        private BigDecimal balance;

// Setter, getter

}

Let's suppose I have as input this list:

Customer custa = new Customer("A", "STANDARD", new BigDecimal("1000"), new BigDecimal("1500"));
    Customer custa1 = new Customer("A", "VIP", new BigDecimal("2000"), new BigDecimal("2500"));
    Customer custb = new Customer("B", "STANDARD", new BigDecimal("3000"), new BigDecimal("3500"));
    Customer custc = new Customer("C", "STANDARD", new BigDecimal("4000"), new BigDecimal("4500"));
    Customer custa2 = new Customer("A", "VIP", new BigDecimal("1500"), new BigDecimal("2500"));
    List<Customer> listCust = new ArrayList<>();
    listCust.add(custa);
    listCust.add(custa1);
    listCust.add(custb);
    listCust.add(custc);
    listCust.add(custa2);

The result should be

[
    {"A", "STANDARD", new BigDecimal("1000"), new BigDecimal("1500")},
    {"A", "VIP", new BigDecimal("3500"), new BigDecimal("5000")},
    {"B", "STANDARD", new BigDecimal("3000"), new BigDecimal("3500")},
    {"C", "STANDARD", new BigDecimal("4000"), new BigDecimal("4500")}
]

I have a beginning of solution, below, but I block at the moment of adding a second aggregation to sum up the balance:

listCust.stream()
                .collect(Collectors.groupingBy(Customer::getName
                    , Collectors.groupingBy(Customer::getType
                        , Collectors.reducing(BigDecimal.ZERO,Customer::getTotal,BigDecimal::add)))
                )
                .entrySet()
over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Collection<Customer> customers = listCust.stream()
                                         .collect(Collectors.toMap(
                                                 customer -> customer.getName() + '-' + customer.getType(),
                                                 Function.identity(), (one, two) -> {
                                                     String name = one.getName();
                                                     String type = one.getType();
                                                     BigDecimal total = one.getTotal().add(two.getTotal());
                                                     BigDecimal balance = one.getBalance().add(two.getBalance());
                                                     return new Customer(name, type, total, balance);
                                                 })).values();
over 4 years ago · Santiago Trujillo Relatório

0

An alternative to using string conncatenation for the intermediate hashmap that provides more flexibility could be to use an Entry. This would allow you to change your grouping types and handles the case of null values if you wrap the key or value in Optional.ofNullable. It does have the drawback of limiting you to only two elements to group by.

Customer custa = new Customer("A", "STANDARD", new BigDecimal("1000"), new BigDecimal("1500"));
Customer custa1 = new Customer("A", "VIP", new BigDecimal("2000"), new BigDecimal("2500"));
Customer custb = new Customer("B", "STANDARD", new BigDecimal("3000"), new BigDecimal("3500"));
Customer custc = new Customer("C", "STANDARD", new BigDecimal("4000"), new BigDecimal("4500"));
Customer custa2 = new Customer("A", "VIP", new BigDecimal("1500"), new BigDecimal("2500"));
Customer custa3 = new Customer(null, "VIP", new BigDecimal("1500"), new BigDecimal("2500"));
List<Customer> listCust = new ArrayList<>();
listCust.add(custa);
listCust.add(custa1);
listCust.add(custb);
listCust.add(custc);
listCust.add(custa2);
listCust.add(custa3);
Collection<Customer> result =  listCust.stream()
        .collect(Collectors.toMap(
                c -> Map.entry(Optional.ofNullable(c.getName()), c.getType()),
                Function.identity(),
                (c1, c2) -> new Customer(c1.getName(),
                        c1.getType(),
                        c1.getTotal().add(c2.getTotal()),
                        c1.getBalance().add(c2.getBalance()))))
        .values();
System.out.println(result);

outupt (inserted newlines for readability)

[
    Customer{name='null', type='VIP', total=1500, balance=2500},
    Customer{name='B', type='STANDARD', total=3000, balance=3500},
    Customer{name='C', type='STANDARD', total=4000, balance=4500},
    Customer{name='A', type='VIP', total=3500, balance=5000},
    Customer{name='A', type='STANDARD', total=1000, balance=1500}
]
over 4 years ago · Santiago Trujillo Relatório

0

You can do it using toMap using the merge function, stream the customer list and collect them into Map using name-type as key, and use the merge function, to sum up the total and balance for customers having same key

Collection<Customer> result = listCust.stream()
            .collect(Collectors.toMap(cu -> cu.getName() + "-" + cu.getType(),
                    Function.identity(), (c1, c2) -> {
                        c1.setTotal(c1.getTotal().add(c2.getTotal()));
                        c1.setBalance(c1.getBalance().add(c2.getBalance()));
                        return c1;
                    })).values();
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda