Java 8 arroyos. Cómo agregar los totales BigDecimal por tipo enumerado en un grano de encargo

Martin:

Es difícil de palabra a la pregunta. Aquí está mi fragmento de código:

Map<PassType, PassTypeRate> ratesPerType = new HashMap<>();

entries.stream().forEach((entry) -> {
    if (!ratesPerType.containsKey(entry.getPassType())) {
        ratesPerType.put(entry.getPassType(), new PassTypeRate(BigDecimal.ZERO, BigDecimal.ZERO));
    }

    if (AgeType.ADULT.equals(entry.getAgeType())) {
        PassTypeRate passTypeRate = ratesPerType.get(entry.getPassType());
        passTypeRate.setAdultRate(passTypeRate.getAdultRate().add(entry.getRate()));
    }
    if (AgeType.CHILD.equals(entry.getAgeType())) {
        PassTypeRate passTypeRate = ratesPerType.get(entry.getPassType());
        passTypeRate.setChildRate(passTypeRate.getChildRate().add(entry.getRate()));
    }
});

Así que entrieses una lista de los granos que tiene una ageType, passType y tasa. Tengo que agregar las tasas totales por 'ageType' y 'passType'.

El grano de PassTypeRate posee un total agregado de tasa para adultos y niños por 'PassType'.

Mi pregunta básica es .... ¿es posible en absoluto volver a escribir el código anterior utilizando Java 8 El receptor o similar? No puedo resolverlo.

Cualquier consejo sería apreciado.

Gracias

Adam Bukowiecki:

Sí, se ve como un buen candidato para implementar con Collectors.toMap. Echar un vistazo a continuación la aplicación (I Lombok usada ( https://projectlombok.org/ ) para que sea más legible):

    Map<PassType, PassTypeRate> group(List<DataEntry> entries) {
        return entries.stream()
                .collect(Collectors.toMap(
                        DataEntry::getPassType,
                        entry -> PassTypeRate.builder()
                                .adultRate(entry.getAgeType() == ADULT ? entry.getRate() : BigDecimal.ZERO)
                                .childRate(entry.getAgeType() == CHILD ? entry.getRate() : BigDecimal.ZERO)
                                .build(),
                        (rate1, rate2) -> PassTypeRate.builder()
                                .childRate(rate1.getChildRate().add(rate2.getChildRate()))
                                .adultRate(rate1.getAdultRate().add(rate2.getAdultRate()))
                                .build()
                ));
    }

Y breve explicación:

  • En primer lugar, tenemos que definir PassTypecomo una clave del mapa

  • En segundo lugar, tenemos que trazar nuestro DataEntrya solas PassTypeRateobjetos. Si esta es Adultla entrada, a continuación, la nueva PassTypeRatetiene que tener un valor en adultRateel campo y cero en childRate. Y viceversa.

  • Sin embargo, algunas entradas pueden tener el mismo PassType! Por lo tanto, tenemos que definir tercera función - la función de fusión. ¿Cómo nos fusionamos PassTypeRateobjetos? Mediante la adición de las tasas correspondientes. Función Merge devuelve nuevo PassTypeRatecomo resultado de la adición de dos PassTypeRateobjetos.

También he preparado una serie de casos de prueba para verificar si funciona la solución - y parece que funciona :) caso de prueba a continuación:

public class RateGroupingTest {

    private RateGrouping subject = new RateGrouping();

    @Test
    public void groups() {
        //given
        List<DataEntry> entries = List.of(
                new DataEntry(ADULT, X, new BigDecimal("3")),
                new DataEntry(ADULT, Y, new BigDecimal("5")),
                new DataEntry(ADULT, Z, new BigDecimal("7")),
                new DataEntry(CHILD, X, new BigDecimal("11")),
                new DataEntry(CHILD, Y, new BigDecimal("13")),
                new DataEntry(CHILD, Z, new BigDecimal("17")),

                new DataEntry(ADULT, X, new BigDecimal("13")),
                new DataEntry(ADULT, Y, new BigDecimal("25")),
                new DataEntry(ADULT, Z, new BigDecimal("37")),
                new DataEntry(CHILD, X, new BigDecimal("411")),
                new DataEntry(CHILD, Y, new BigDecimal("513")),
                new DataEntry(CHILD, Z, new BigDecimal("617"))
        );

        //when
        Map<PassType, PassTypeRate> actual = subject.group(entries);

        //then
        assertThat(actual.get(PassType.X))
                .isEqualTo(
                        PassTypeRate.builder()
                                .childRate(new BigDecimal("422"))
                                .adultRate(new BigDecimal("16"))
                                .build()
                );
        assertThat(actual.get(PassType.Y))
                .isEqualTo(
                        PassTypeRate.builder()
                                .childRate(new BigDecimal("526"))
                                .adultRate(new BigDecimal("30"))
                                .build()
                );
        assertThat(actual.get(PassType.Z))
                .isEqualTo(
                        PassTypeRate.builder()
                                .childRate(new BigDecimal("634"))
                                .adultRate(new BigDecimal("44"))
                                .build()
                );
    }
}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=335165&siteId=1
Recomendado
Clasificación