Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

419
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda