Java 8 带有可选键的映射,以可选值作为键进行映射

问题描述 投票:0回答:2

我有一个地图,需要获取一个包含选项实际值的地图(如果存在的话)(地图)。

这有效:

private Map<Price, String> getPricesForUserRelatedPrices(List<SpecialPrice> prices) {
    Map<Optional<Price>, String> pricesWithOptional = prices.stream().collect(Collectors.toMap(this::getPrice, this::getName));
    Map<Price, String> existingPrices = pricesWithOptional .entrySet().stream().filter(e -> e.getKey().isPresent()).collect(Collectors.toMap(e -> e.getKey().get(), Entry::getValue));
    return existingPrices;
}

getPrice 可能会返回一个可选值,因此需要过滤空条目。

带有可选键的地图当然只是一个临时地图,以使其具有一定的可读性。

以老式/非 lambda 方式,我会这样做:

private Map<Price, String> getPricesForUserRelatedPrices(List<SpecialPrice> prices) {
Map<Price, String> existingPrices = new HashMap<>();
for(SpecialPrice p: prices){
    Optional<Price> price = getPrice(p);
    if(price.isPresent())
        existingPrices.put(price.get(), getName(price));
}
return existingPrices;

}

还有更优雅的方式吗?

java lambda java-8 collectors
2个回答
4
投票

是的,只有在导出

pricesWithOptional
后完全丢弃
existingPrices
时,才有替代方案,这与您已经达到的位置相比是退一步。

Map<Price, String> existingPrices = prices.stream()
        .map(p -> Map.entry(getPrice(p), getName(p))) // to avoid multiple calls to these
        .filter(e -> e.getKey().isPresent())
        .collect(Collectors.toMap(entry -> entry.getKey().get(),
                Map.Entry::getValue));

注意:如果

getPrice
getName
都很昂贵,并且您可能不会制作
getName
,除非您确定
getPrice
的存在,我宁愿建议保留
for
循环以提高可读性.

Map<Price, String> existingPrices = new HashMap<>();
for (SpecialPrice specialPrice : prices) {
    Optional<Price> price = getPrice(specialPrice);
    if (price.isPresent()) {
        String name = getName(specialPrice);
        existingPrices.put(price.get(), name);
    }
}

0
投票

我想补充一下@Naman的答案

如果

getName
成本较高,又想保持函数式风格,可以将调用推迟到收集阶段:

private Map<Price, String> getPricesForUserRelatedPrices(List<SpecialPrice> prices) {
        return prices.stream()
            .map(p -> Map.entry(getPrice(p), p))
            .filter(e -> e.getKey().isPresent())
            .collect(Collectors.toMap(entry -> entry.getKey().get(),
                entry -> getName(entry.getValue())));
    }
© www.soinside.com 2019 - 2024. All rights reserved.