Map и orElse, возвращающие разные подтипы - PullRequest
4 голосов
/ 10 июля 2019

У меня есть две функции - одна возвращает 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. Набор не может быть преобразован в java.util.List

Я могу понять, что здесь происходит. Но есть ли способ достичь чего-то подобного, не выполняя такого сложного утверждения, как это?

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

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

    return getStringSet();
}

Ответы [ 2 ]

5 голосов
/ 10 июля 2019

Вы можете использовать универсальную спецификацию типа, чтобы getStringList считался Collection<String>:

return factor.filter(LambdaTest::someCondition)
             .<Collection<String>> map(LambdaTest::getStringList)
             .orElse(getStringSet());
1 голос
/ 10 июля 2019

Не уверен, было ли это очевидно и указано в последней части вопроса, но вы также можете изменить сигнатуру метода 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()));
}
...