Map和orElse返回不同​​的子类型

时间:2019-07-10 18:39:44

标签: java lambda compiler-errors

我有两个函数-一个返回Set<String>,另一个返回List<String>

private static List<String> getStringList(final String factor) {
    ....
}

private static Set<String> getStringSet() {
    ....
}

现在,我具有一个返回Collection<String>的函数,而该函数又会根据特定条件调用上述函数。我想做这样的事情:

private static Collection<String> getStringCollection() {
    Optional<String> factor = getFactor();
    return factor.filter(LambdaTest::someCondition)
            .map(LambdaTest::getStringList)
            .orElse(getStringSet());
}

但是我得到这个错误

  

错误:(24,37)java:不兼容的类型:java.util.Set无法转换为java.util.List

我知道这里发生了什么。但是,有没有一种方法可以完成类似的工作而无需执行类似的if-else语句呢?

private static Collection<String> getStringCollection() {
    Optional<String> factor = getFactor();

    if(factor.isPresent() && someCondition(factor.get())) {
        return getStringList(factor.get());
    }

    return getStringSet();
}

2 个答案:

答案 0 :(得分:5)

您可以使用通用类型规范来强制将getStringList视为Collection<String>

return factor.filter(LambdaTest::someCondition)
             .<Collection<String>> map(LambdaTest::getStringList)
             .orElse(getStringSet());

答案 1 :(得分:1)

不确定这是否很明显并在问题的后面部分进行了说明,但是您还可以做的是更改getStringList方法的签名以返回Collection<String>,并保持其实现不变和以前一样。

因此完整的实现应如下所示:

Collection<String> getStringList(final String factor) { ... }

Set<String> getStringSet() { ... }

private Collection<String> getStringCollection() {
    Optional<String> factor = getFactor();
    return factor.filter(this::someCondition)
            .map(this::getStringList)
            .orElseGet(this::getStringSet);
}

另一种选择是初始化Set中的orElse以使用List返回new ArrayList<>

private Collection<String> getStringCollection() {
    Optional<String> factor = getFactor();
    return factor.filter(this::someCondition)
            .map(this::getStringList)
            .orElse(new ArrayList<>(getStringSet()));
}