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

220
Vistas
Java 8 Lambda Collectors.sumingLong ¿columnas múltiples?

Tengo la definición de POJO de la siguiente manera:

 class EmployeeDetails{ private String deptName; private Double salary; private Double bonus; ... }

Actualmente, tengo una expresión lambda para Group By 'deptName' como:

 $set.stream().collect(Collectors.groupingBy(EmployeeDetails::getDeptName, Collectors.summingLong(EmployeeDetails::getSalary));

Pregunta ¿Es posible sumar más de una columna? ¿Necesito calcular la suma en ambos campos, salary and bonus en una expresión en lugar de varias veces?

La representación SQL sería:

 SELECT deptName,SUM(salary),SUM(bonus) FROM TABLE_EMP GROUP BY deptName;
about 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Debe crear una clase adicional que contenga sus 2 números resumidos (salario y bonificación). Y un coleccionista personalizado.

digamos que tienes

 private static final class Summary { private double salarySum; private double bonusSum; public Summary() { this.salarySum = 0; this.bonusSum = 0; } @Override public String toString() { return "Summary{" + "salarySum=" + salarySum + ", bonusSum=" + bonusSum + '}'; } }

por tener sumas. Entonces necesitas un colector como este:

 private static class EmployeeDetailsSummaryCollector implements Collector<EmployeeDetails, Summary, Summary> { @Override public Supplier<Summary> supplier() { return Summary::new; } @Override public BiConsumer<Summary, EmployeeDetails> accumulator() { return (summary, employeeDetails) -> { summary.salarySum += employeeDetails.salary; summary.bonusSum += employeeDetails.bonus; }; } @Override public BinaryOperator<Summary> combiner() { return (summary, summary1) -> { summary.salarySum += summary1.salarySum; summary.bonusSum += summary1.bonusSum; return summary; }; } @Override public Function<Summary, Summary> finisher() { return Function.identity(); } @Override public Set<Characteristics> characteristics() { return EnumSet.of(Collector.Characteristics.IDENTITY_FINISH); } }

Con estas clases puedes recopilar tus resultados como

 final List<EmployeeDetails> employees = asList( new EmployeeDetails(/* deptName */"A", /* salary */ 100d, /* bonus */ 20d), new EmployeeDetails("A", 150d, 10d), new EmployeeDetails("B", 80d, 5d), new EmployeeDetails("C", 100d, 20d) ); final Collector<EmployeeDetails, Summary, Summary> collector = new EmployeeDetailsSummaryCollector(); final Map<String, Summary> map = employees.stream() .collect(Collectors.groupingBy(o -> o.deptName, collector)); System.out.println("map = " + map);

Que imprime esto:

 map = {A=[salary=250.0, bonus=30.0], B=[salary=80.0, bonus=5.0], C=[salary=100.0, bonus=20.0]}
about 4 years ago · Santiago Trujillo Denunciar

0

Sé que tienes tu respuesta, pero aquí está mi opinión (estaba escribiendo mientras se publicaba la otra). Ya hay un Pair en Java en forma de AbstractMap.SimpleEntry .

 System.out.println(Stream.of(new EmployeeDetails("first", 50d, 7d), new EmployeeDetails("first", 50d, 7d), new EmployeeDetails("second", 51d, 8d), new EmployeeDetails("second", 51d, 8d)) .collect(Collectors.toMap(EmployeeDetails::getDeptName, ed -> new AbstractMap.SimpleEntry<>(ed.getSalary(), ed.getBonus()), (left, right) -> { double key = left.getKey() + right.getKey(); double value = left.getValue() + right.getValue(); return new AbstractMap.SimpleEntry<>(key, value); }, HashMap::new)));
about 4 years ago · Santiago Trujillo Denunciar

0

Agrupar por es una operación terminal que produce un mapa. El mapa producido por groupingBy en el siguiente código es Map<String, List<EmployeeDetails>> . Creo una nueva transmisión usando el método Map entrySet. Luego creo un nuevo Mapa usando Collectors.toMap . Este enfoque utiliza el encadenamiento de métodos para evitar crear otra clase y crear un código más conciso.

 details.stream() .collect(Collectors.groupingBy(EmployeeDetails::getDeptName)) .entrySet() .stream() .collect(Collectors.toMap(x->x.getKey(), x->x.getValue() .stream() .mapToDouble(y -> y.getSalary() + y.getBonus()) .sum()));
about 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