Какие ключевые элементы функционального программирования были добавлены в Java 8?

«Какие ключевые элементы функционального программирования были добавлены в Java 8?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Java 8 представила несколько фундаментальных возможностей, позволивших писать более декларативный и выразительный код в функциональном стиле.

1. Лямбда-выражения (Lambda Expressions)

  • Что: Краткий синтаксис для реализации функциональных интерфейсов (анонимные функции).
  • Зачем: Устраняет шаблонный код анонимных классов.
  • Пример:
    
    // До Java 8: анонимный класс Comparator
    Collections.sort(list, new Comparator<String>() {
    public int compare(String a, String b) {
        return a.compareTo(b);
    }
    });

// Java 8: лямбда-выражение Collections.sort(list, (a, b) -> a.compareTo(b));


### 2. Функциональные интерфейсы (Functional Interfaces) и `java.util.function`
*   **Что:** Интерфейс с ровно одним абстрактным методом (SAM). Аннотация `@FunctionalInterface` — документальная.
*   **Зачем:** Целевой тип для лямбд. Готовые интерфейсы для типичных операций.
*   **Примеры:**
    *   `Predicate<T>` — принимает `T`, возвращает `boolean` (`test`).
    *   `Function<T,R>` — принимает `T`, возвращает `R` (`apply`).
    *   `Consumer<T>` — принимает `T`, не возвращает ничего (`accept`).
    *   `Supplier<T>` — не принимает, возвращает `T` (`get`).

### 3. Stream API
*   **Что:** Абстракция для выполнения операций над последовательностями элементов (коллекции, массивы, I/O) в функциональном и декларативном стиле.
*   **Зачем:** Позволяет писать сложные операции обработки данных (фильтрация, преобразование, агрегация) лаконично и часто более эффективно (параллельные стримы).
*   **Пример:**
```java
List<String> result = names.stream()          // Источник
        .filter(name -> name.startsWith("A")) // Промежуточная операция
        .map(String::toUpperCase)            // Промежуточная операция
        .sorted()                            // Промежуточная операция
        .collect(Collectors.toList());       // Терминальная операция

4. Ссылки на методы (Method References) ::

  • Что: Еще более компактная замена лямбдам, когда лямбда просто вызывает существующий метод.
  • Пример: System.out::println эквивалентно x -> System.out.println(x).

5. Методы по умолчанию в интерфейсах (Default Methods)

  • Что: Реализация метода в интерфейсе с ключевым словом default.
  • Зачем: Обеспечение обратной совместимости при добавлении новых методов в API (например, в Collection.stream()).
    interface List<E> extends Collection<E> {
    default void sort(Comparator<? super E> c) {
        Collections.sort(this, c);
    }
    }

    Эти изменения сместили парадигму Java в сторону гибридного (объектно-ориентированного и функционального) стиля программирования.