Возврат из lambda forEach () в java
Я пытаюсь изменить некоторые циклы for-each на lambda forEach()
-методы для обнаружения возможностей лямбда-выражений. Представляется возможным следующее:
ArrayList<Player> playersOfTeam = new ArrayList<Player>();
for (Player player : players) {
if (player.getTeam().equals(teamName)) {
playersOfTeam.add(player);
}
}
С лямбда forEach()
players.forEach(player->{if (player.getTeam().equals(teamName)) {playersOfTeam.add(player);}});
но следующий не особенно конечно интересно наблюдать:
for (Player player : players) {
if (player.getName().contains(name)) {
return player;
}
}
С лямбда
players.forEach(player->{if (player.getName().contains(name)) {return player;}});
что-то не так в синтаксисе последней строки или невозможно вернуться из forEach()
способ?
4 ответа:
The
return
там возвращается из лямбда-выражения, а не от содержания метода. ВместоforEach
вам нужноfilter
потока:players.stream().filter(player -> player.getName().contains(name)) .findFirst().orElse(null);
здесь
filter
ограничивает поток теми элементами, которые соответствуют предикату, иfindFirst
затем возвращаетOptional
С первой соответствующей записью.это выглядит менее эффективным, чем подход для цикла, но на самом деле
findFirst()
может короткое замыкание - оно не производит весь фильтрованный поток и затем извлеките из него один элемент, а он фильтрует только столько элементов, сколько ему нужно, чтобы найти первый соответствующий. Вы также можете использоватьfindAny()
вместоfindFirst()
если вы не обязательно заботитесь о получении первый соответствующий игрок из (заказанного) потока, но просто любой соответствующий элемент. Это позволяет повысить эффективность при наличии параллелизма.
Я предлагаю вам сначала попытаться понять Java 8 во всей картине, самое главное в вашем случае это будут потоки, лямбды и ссылки на методы.
вы должны никогда преобразование существующего кода в код Java 8 на построчной основе, вы должны извлечь функции и конвертировать их.
в вашем первом случае я определил следующее:
- вы хотите добавить элементы входной структуры в выходной список, если они соответствуют некоторому предикату.
давайте посмотрим, как мы это делаем, мы можем сделать это следующим образом:
List<Player> playersOfTeam = players.stream() .filter(player -> player.getTeam().equals(teamName)) .collect(Collectors.toList());
что вы делаете здесь:
- превратите свою входную структуру в поток (я предполагаю, что она имеет тип
Collection<Player>
, теперь у вас естьStream<Player>
.- отфильтровать все нежелательные элементы с помощью
Predicate<Player>
, сопоставление каждого игрока с логическим true, если он хочет быть сохранен.- соберите полученные элементы в a список, с помощью
Collector
, здесь мы можем использовать один из стандартных коллекторов библиотеки, которыйCollectors.toList()
.это также включает в себя два момента:
- код против интерфейсы, поэтому кодекс в отношении
List<E>
overArrayList<E>
.- используйте алмазный вывод для параметра типа в
new ArrayList<>()
, вы используете Java 8, в конце концов.теперь перейдем ко второму пункту:
вы снова хотите конвертировать что-то из устаревшей Java в В Java 8, не глядя на картину. На эту часть уже ответили @IanRoberts, хотя я думаю, что вам нужно сделать
players.stream().filter(...)...
над тем, что он предложил.
вот что мне помогло:
List<RepositoryFile> fileList = response.getRepositoryFileList(); RepositoryFile file1 = fileList.stream().filter(f -> f.getName().contains("my-file.txt")).findFirst().orElse(null);
принято от Java 8 поиск конкретного элемента в списке с лямбда