簡體   English   中英

如何使Map可選的值是否存在

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

我有一個包含許多可選值的Map:

Map<MyCoolKey, Optional<MyCoolValue>>

我想將此Map轉換為Optional<Map<>>

Optional<Map<MyCoolKey, MyCoolValue>>
  • 如果每個Optional<MyCoolValue>都存在:應該存在Optional<Map<>>
  • 如果任何 Optional<MyCoolValue>不存在: Optional<Map<>>應該不存在。

我試過這個,我懷疑我的代碼會起作用,但它有點啰嗦:

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;
                                        }
                                )
                        )
                );

有一個更好的方法嗎? “更好”意味着正確,表現,美麗。 我更喜歡能夠在一個流中完成整個操作的答案。

下面是純流溶液的例子(不if S和三元運營商)

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()
        ))
    );

這不是過於復雜 - 過濾和映射是流的用途!

以下方法完成工作:

Map<MyCoolKey, Optional<MyCoolValue>> input;
Optional<Map<MyCoolKey, MyCoolValue>> output = convertMapWithOptionals(input);

我想出了這種方法的兩種“味道”:

1)不情願:首先檢查所有,然后開始轉換

<K, V> Optional<Map<K, V>> convertMapWithOptionals(Map<K, Optional<V>> map) {
    if (!map.values().stream().allMatch(Optional::isPresent)) {
        return Optional.empty();
    }
    return Optional.of(map.entrySet().stream().collect(Collectors.toMap(
            Map.Entry::getKey, entry -> entry.getValue().get()
    )));
}

2)渴望:必要時開始轉換和中止

<K, V> Optional<Map<K, V>> convertMapWithOptionals(Map<K, Optional<V>> map) {
    Map<K, V> result = new HashMap<>();
    for (Map.Entry<K, Optional<V>> entry : map.entrySet()) {
        if (!entry.getValue().isPresent()) {
            return Optional.empty();
        }
        result.put(entry.getKey(), entry.getValue().get());
    }
    return Optional.of(result);
}

如果我理解正確的問題,你可以使用reduce而不是collect 它允許您在收集期間更改accumulator

    Optional<Map<MyCoolKey, MyCoolValue>> optionalMap = myCoolMap
            .entrySet()
            .stream()
            .reduce(Optional.<Map<MyCoolKey, MyCoolValue>>of(new HashMap<>()),
                    (acc, entry) -> {
                        if (!acc.isPresent()) {
                            return acc;
                        }
                        if (!entry.getValue().isPresent()) {
                            return Optional.empty();
                        }
                        acc.get().put(entry.getKey(), entry.getValue().get());
                        return acc;
                    },
                    (acc, acc1) -> {
                        if (acc.isPresent() && acc1.isPresent()) {
                            acc.get().putAll(acc1.get());
                            return acc;
                        }
                        return Optional.empty();
                    }
            );

我認為你通過嘗試將所有邏輯放在流中來過度復雜化。 只需過濾掉空的Optional s,看看元素的數量是否相同:

Optional<Map<MyCoolKey, MyCoolValue>> result = Optional.of(
    map.entrySet()
        .stream()
        .filter(e -> e.getValue().isPresent())
        .collect(
            Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get())
        )
)
.filter(x-> x.size() == map.size());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM