I have a Map<Optional, String> and need to get a map with the actual values of the optionals, if they are present (Map<Price, String>).
This works:
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;
}
The getPrice might return an optional, therefore the empty entries need to be filtered.
The Map with the optional as key is of course only a temporary map to have it somewhat readable.
In the old fashioned/ non-lambda way I would just do this:
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;
}
Is there a more elegant way?
Yes there is an alternate only if you completely discard pricesWithOptional
after you have derived existingPrices
and that is a step back from where you have already reached.
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));
Note: If both getPrice
and getName
are costly and you would likely not make getName
unless you are sure of getPrice
's presence, I would rather suggest staying with the for
loop for readability.
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);
}
}