首页 > 解决方案 > Java8 收集地图

问题描述

我有这个对象:

public class MenuPriceByDay implements Serializable {

    private BigDecimal avgPrice;
    private BigDecimal minPrice;
    private BigDecimal maxPrice;
    private Date updateDate;

..
}

还有这个:

public class Statistics {

     double min;
     double max;
     double average;

     public Statistics() {
        super();
     }



    public Statistics(double min, double max, double average) {
        super();
        this.min = min;
        this.max = max;
        this.average = average;
    }



}

以及价格清单:

List<MenuPriceByDay> prices = new ArrayList<MenuPriceByDay>();

我想转换为地图:

Map<LocalDate, Statistics> last30DPerDay =  

        prices
            .stream()
            .collect(Collectors.toMap(MenuPriceByDay::getUpdateDate, p -> new Statistics(   p.getAvgPrice().doubleValue(),
                    p.getMaxPrice().doubleValue(),
                    p.getMinPrice().doubleValue())));

但我遇到了编译问题:

Type mismatch: cannot convert from Map<Date,Object> to 
 Map<LocalDate,Statistics>

标签: javacollectionsjava-8functional-programmingjava-stream

解决方案


请注意,当您使用时,如果您有重复的密钥,Collectors.toMap您可以获得。IllegalStateException

如果映射的键包含重复项(根据 Object.equals(Object)),则在执行收集操作时会引发 IllegalStateException。

你可以toMap(keyMapper, valueMapper, mergeFunction)改用。也有解决方案groupingBy,在这种情况下,您应该决定在复制密钥时必须使用哪个统计信息:

Map<LocalDate, Optional<Statistics>> map = prices.stream()
            .collect(groupingBy(p -> p.getUpdateDate()
                            .toInstant()
                            .atZone(ZoneId.systemDefault())
                            .toLocalDate(),
                    mapping(p-> new Statistics(
                            p.getMinPrice().doubleValue(),
                            p.getAvgPrice().doubleValue(),
                            p.getMaxPrice().doubleValue()),
                            reducing((s1, s2) -> ???)      // here

推荐阅读