How to make Map Optional on whether its every optional value is present

Birchlabs :

I have a Map with many Optional values:

Map<MyCoolKey, Optional<MyCoolValue>>

I would like to transform this Map into an Optional<Map<>>:

Optional<Map<MyCoolKey, MyCoolValue>>
  • If every Optional<MyCoolValue> is present: the Optional<Map<>> should be present.
  • If any Optional<MyCoolValue> is non-present: the Optional<Map<>> should be non-present.

I attempted this, and I suspect that my code will work, but it's a bit long-winded:

final Map<MyCoolKey, Optional<MyCoolValue>> myCoolMap;
final Optional<Map<MyCoolKey, MyCoolValue>> optionalMap = myCoolMap
                .entrySet()
                .stream()
                .map(e -> e
                        .getValue()
                        .flatMap(value -> Optional.<Map.Entry<MyCoolKey, MyCoolValue>>of(
                                new AbstractMap.SimpleEntry<>(
                                        e.getKey(),
                                        value
                                )
                        ))
                )
                .collect(
                        () -> Optional.<Map<MyCoolKey, MyCoolValue>>of(new HashMap<>()),
                        (optAcc, optEntry) -> optAcc.flatMap(
                                acc -> optEntry.map(
                                        entry -> {
                                            acc.put(entry.getKey(), entry.getValue());
                                            return acc;
                                        })
                        ),
                        (optAcc1, optAcc2) -> optAcc1.flatMap(
                                acc1 -> optAcc2.map(
                                        acc2 -> {
                                            acc1.putAll(acc2);
                                            return acc1;
                                        }
                                )
                        )
                );

Is there a better way to do this? "Better" means correctness, performance, beauty. I would prefer an answer that can do the whole operation in one stream.

Danon :

Here's an example of pure stream solution (without ifs and ternary operators)

final Map<MyCoolKey, Optional<MyCoolValue>> myCoolMap = new HashMap<>();

Optional<Map<MyCoolKey, MyCoolValue>> output = Optional.of(myCoolMap)
    .filter(map -> map.values().stream().allMatch(Optional::isPresent))
    .map(map -> map
        .entrySet()
        .stream()
        .collect(toMap(
            Map.Entry::getKey,
            entry -> entry.getValue().get()
        ))
    );

It's not over-complicating - filtering and mapping are what's streams are for!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=113545&siteId=1