
Одной из наиболее интересных функций является новый API java.util.stream , который, как утверждает Javadoc, позволяет
операции в функциональном стиле над потоками элементов, такие как преобразования карты-сокращения в коллекциях
Объедините этот новый API с лямбда-выражениями, и вы получите краткий, но мощный синтаксис, который значительно упрощает код за счет применения проекций.
Взять, к примеру, якобы простую задачу фильтрации коллекции. В этом случае простая Collection типов Message , созданная так:
Создание коллекции сообщений
|
1
2
3
4
5
|
List<Message> messages = new ArrayList<>();messages.add(new Message("aglover", "foo", 56854));messages.add(new Message("aglover", "foo", 85));messages.add(new Message("aglover", "bar", 9999));messages.add(new Message("rsmith", "foo", 4564)); |
В этой коллекции я бы хотел отфильтровать Message с delay (3-й параметр конструктора), превышающей 3000 секунд.
До Java 8 вы могли вручную заклинить такую логику следующим образом:
Фильтрация стиля старой школы
|
1
2
3
4
5
|
for (Message message : messages) { if (message.delay > 3000) { System.out.println(message); }} |
Однако в Java 8 эта работа становится намного более лаконичной. Коллекции теперь поддерживают stream метод, который преобразует базовую структуру данных в stream объектов, способный к итерации, и, таким образом, разрешает новое поколение функциональных операций, использующих лямбда-выражения. Большинство из этих операций также могут быть связаны. Эти цепочечные методы называются промежуточными , а методы, которые не могут быть связаны, обозначаются как терминальные .
Вкратце, лямбда-выражения во многом похожи на анонимные классы, но с гораздо меньшим синтаксисом. Например, если вы посмотрите на Javadoc для параметра метода Stream , вы увидите, что он принимает тип Predicate . Тем не менее, вам не нужно реализовывать этот интерфейс, как, скажем, до Java 8 с анонимным классом. Следовательно, лямбда-выражение Predicate для фильтрации всех значений delay больше 3000 будет:
Лямбда-выражение
|
1
|
x -> x.delay > 3000 |
Где x — параметр, передаваемый для каждого значения в потоке, и все, что находится справа от -> является оцененным выражением.
Объединение всего этого в Java 8 дает:
Потоковые лямбды!
|
1
|
messages.stream().filter(m -> m.delay > 3000).forEach(item -> System.out.println(item)); |
Интересно, что благодаря некоторым другим новым функциям Java 8, лямбда forEach может быть упрощена до:
Потоковые лямбды еще короче!
|
1
|
messages.stream().filter(m -> m.delay > 3000).forEach(System.out::println); |
Поскольку параметр forEach lambda просто используется println , Java 8 теперь позволяет вам полностью удалить этот параметр.
Ранее я упоминал, что потоки позволяют вам связывать лямбды — в приведенном выше случае метод filter является промежуточным, а forEach — терминальным. Другими промежуточными методами, которые сразу распознаются функциональными программистами, являются: map , flatMap и flatMap , если назвать несколько.
Чтобы уточнить, я хотел бы найти все Message с задержкой более 3000 секунд и суммировать общее время задержки. Без функциональной магии я мог бы написать:
Прозаическая Ява
|
1
2
3
4
5
6
|
long totalWaitTime = 0;for (Message message : messages) { if (message.delay > 3000) { totalWaitTime += message.delay; }} |
Тем не менее, с Java 8 и немного функционала, вы можете получить более элегантную конструкцию кода, например:
Java 8 элегантность
|
1
|
long totWaitTime = messages.stream().filter(m -> m.delay > 3000).mapToLong(m -> m.delay).sum(); |
Обратите внимание, как я могу mapToLong методы filter и mapToLong вместе с терминальной sum . Кстати, для метода sum требуется определенный метод стиля карты, который выдает коллекцию примитивных типов, таких как mapToLong , mapToInt и т. Д.
Функциональное программирование стиля как ключевая особенность языка — поразительно мощная конструкция. И хотя многие из этих методов были доступны в различных сторонних библиотеках, таких как языки Guava и JVM, таких как Scala и Groovy, включение этих функций в ядро языка, несомненно, охватит более широкую аудиторию разработчиков и окажет наибольшее влияние на ландшафт развития.
Java 8, без сомнения, радикально меняет язык Java в лучшую сторону.
| Ссылка: | Функциональная разжигание Java 8 от нашего партнера JCG Эндрю Гловера в блоге The Disco Blog . |