Java 8 Optional и flatMap — что не так?

Какой-то кусок кода:

public class Player {
    Team team;
    String name;
}

public class Team {
    List<Player> players;
}

public class Demo {

    @Inject
    TeamDAO teamDAO;

    @Inject
    PlayerDAO playerDAO;

    List<String> findTeamMatesNames(String playerName) {
        Optional<Player> player = Optional.ofNullable(playerDAO.get(playerName));

        return player.flatMap(p -> teamDAO.findPlayers(p.team))
            .map(p -> p.name)
            .orElse(Collections.emptyList());
    }
}

Почему я не могу этого сделать? В методе flatMap я получаю сообщение об ошибке «Несоответствие типов: невозможно преобразовать из списка в необязательный».

Моя цель:

  1. Если присутствует необязательное, я хочу получить список элементов на основе этого необязательного свойства объекта.

  2. Если необязательного нет, я хочу вернуть пустой список


person Dariusz Mydlarz    schedule 08.10.2014    source источник
comment
Какая у вас ошибка?   -  person talex    schedule 08.10.2014
comment
Какая у вас ошибка? А что делает teamDAO.finPlayers?   -  person user2504380    schedule 08.10.2014
comment
Откуда team в findTeamMatesNames?   -  person coolcfan    schedule 08.10.2014
comment
Дело не в том, что вы просите. В flatMap я получаю: Несоответствие типов: невозможно преобразовать из List‹Player› в Optional‹Object›   -  person Dariusz Mydlarz    schedule 08.10.2014
comment
@coolcfan Его код не работает, команда должна быть игроком.   -  person Dirk Lachowski    schedule 08.10.2014
comment
Похоже, вы смешиваете поток и необязательный API. flatMap() в Optional предназначен для распаковки вложенных опций, но ваша лямбда возвращает список Players, а не Optional‹Player›.   -  person Dirk Lachowski    schedule 08.10.2014
comment
@coolcfan извините, я ошибся, теперь все должно быть в порядке   -  person Dariusz Mydlarz    schedule 08.10.2014
comment
@DirkLachowski, как я могу достичь своей цели?   -  person Dariusz Mydlarz    schedule 08.10.2014


Ответы (1)


Вы можете использовать map для выполнения нужной операции. Операция map не будет выполняться, если Optional пуста, но снова останется пустым Optional. После этого вы можете указать резервное значение:

player.map(p -> teamDAO.findPlayers(p.team)).orElse(Collections.emptyList())

Преобразование List из Player в List с именем игрока Strings не может быть выполнено с помощью Optional; это Stream задача:

Optional<Player> player = Optional.ofNullable(playerDAO.get(playerName));
return player.map(p -> teamDAO.findPlayers(p.team)
                           .stream().map(tp -> tp.name).collect(Collectors.toList()))
             .orElse(Collections.emptyList());
person Holger    schedule 08.10.2014
comment
Я не знал, что мне нужно выполнять следующие операции внутри первой функции карты. Спасибо! - person Dariusz Mydlarz; 08.10.2014
comment
@dmydlarz: это также можно сделать позже, например. player.map(p -> teamDAO.findPlayers(p.team)).orElse(Collections.emptyList()) .stream().map(tp -> tp.name).collect(Collectors.toList()) имеет ту же семантику, но подразумевает ненужную операцию сбора, выполняемую над пустым потоком в случае пустого Optional. - person Holger; 08.10.2014