Search code examples
javajava-8java-streamcollectors

How to combine stats and mapper in streams?


public static PriceRangeData getCanonicalPriceRange(final ProductData productDataParent) {
    if (MapUtils.isNotEmpty(productDataParent.getAggregates())
            && null != productDataParent.getAggregates().get(DtCoreConstants.RANGED_DATA)) {
        final PriceRangeData data = new PriceRangeData();
        final Map<String, Double> mapPrices = productDataParent.getRangeMapPrices();
        final List<ProductData> ranges = (List<ProductData>) productDataParent.getAggregates()
                .get(DtCoreConstants.RANGED_DATA);
        if(MapUtils.isNotEmpty(mapPrices)) {
            ranges.stream()
            .map(productData -> getMapUpdatedData(mapPrices, productData));
        }
        final DoubleSummaryStatistics stats = ranges.stream()
                .collect(Collectors.summarizingDouble(ProductData::getRawPrice));
        if (null != stats) {
            PriceData minPrice = new PriceData();
            minPrice.setValue(new BigDecimal(stats.getMin()));
            data.setMinPrice(minPrice);
            PriceData maxPrice = new PriceData();
            maxPrice.setValue(new BigDecimal(stats.getMax()));
            data.setMaxPrice(maxPrice);
        }
        return data;
    }
    return null;
}

private static ProductData getMapUpdatedData(final Map<String, Double> mapPrices, final ProductData productData) {
    if (mapPrices.containsKey(productData.getCode())) {
        productData.setRawPrice(mapPrices.get(productData.getCode()));
    }
    return productData;
}

Is there a way to combine

if(MapUtils.isNotEmpty(mapPrices)) {
            ranges.stream()
            .map(productData -> getMapUpdatedData(mapPrices, productData));
        }

and

final DoubleSummaryStatistics stats = ranges.stream()
                .collect(Collectors.summarizingDouble(ProductData::getRawPrice));

by referring to a local method for getRawPrice rather than ProductData.getRawPrice. Currently we are updating the rawPrice to the ones from mapPrice if they exist and then redoing the stream for stats. Is there a way to do it without having to update first, rather just use the local method to input the values to compute stats in summarizingDouble

Like using below in Collectors.summarizingDouble method

private Double getRawPrice(final Map<String, Double> mapPrices, final ProductData productData) {
        if (mapPrices.containsKey(productData.getCode())) {
            return mapPrices.get(productData.getCode());
        }
        return productData.getRawPrice();
    }

Solution

  • As far as I understand you need

     ranges.stream()
            .map(productData -> mapPrices.getOrDefault(productData.getCode(), productData.getRawPrice())) 
            .collect(Collectors.summarizingDouble(x->x));