1.4. FP, Lambda, Stream API Flashcards

1
Q

Что такое lambda-выражение?

A

Лямбда-выражение - это краткая форма записи реализации абстрактного метода функционального интерфейса, которая может быть передана в качестве параметра.

  • Синтаксис: (параметры) -> { тело }.
  • В Java лямбда-выражение выполняет роль анонимной функции.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Что такое функциональные интерфейсы?

A

Функциональный интерфейс - это интерфейс, который содержат только один абстрактный метод, не считая методы класса Object.

  • Обозначается аннотацией @FunctionalInterface.
  • Примеры: Runnable, Comparator, Function, Supplier, Operator.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Перечислите функциональные интерфейсы из пакета java.util.function.

A
  • Supplier - ничего не принимает, возвращает объект.
  • Consumer (BiConsumer) - принимает объект и выполняет действие с ним, ничего не возвращает.
  • Predicate (BiPredicate) - проверяет условие, возвращает boolean.
  • Function (BiFunction) - преобразует входной параметр в значение другого типа.
  • UnaryOperator (BinaryOperator) - разновидность Function, где входной и выходной типы совпадают.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Что такое функции высшего порядка?

A

Функции высшего порядка — это функции, которые принимают или возвращают другие функции.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Какие функциональные интерфейсы из пакета java.util.function поддерживают функции высшего порядка?

A
  • Function, BiFunction: методы andThen(), compose().
  • Predicate, BiPredicate: методы and(), or(), negate().
  • Consumer, BiConsumer: метод andThen().

compose() - сначала выполнить указанную функцию, а затем применить текущую. Последовательность происходит в обратном порядке, чем при использовании andThen.

negate() - меняет результат текущего предиката на противоположный (true → false, false → true).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Что такое ссылки на методы?

A

Ссылки на методы (method references) — это сокращенный способ записи существующих методов в лямбда-выражении.

Типы ссылок:

  • Статический метод: СlassName::method
  • Метод объекта: instance::method
  • Конструктор: ClassName::new

Сигнатура ссылки на метод/конструктор должна совпадать с сигнатурой абстрактного метода функционального интерфейса.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Что такое ссылки на конструкторы?

A

Ссылки на конструкторы (ClassName::new) используются для создания объектов.

  • Без параметров: реализует Supplier<T>.</T>
  • С параметрами: реализует Function<T, R> или BiFunction<T, U, R>.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Расскажите о зоне видимости переменных в lambda – выражениях?

A
  • Поля класса и статические переменные: доступны для чтения и изменения.
  • Локальные переменные: доступны только для чтения, должны быть final или effectively final.
  • Переменные внутри лямбда-выражения: доступны только внутри.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Как быть в ситуации, если внутри lambda - выражения операторы могут выкинуть исключение?

A
  • Преобразовать исключение в RuntimeException в try-catch.
  • Использовать функциональный интерфейс, который декларирует checked exceptions в throws
    т.к. в Java нельзя выбросить checked исключение из метода, если оно не указано в throws.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Что такое Stream API?

A

Stream API - это инструмент для обработки данных в функциональном стиле через цепочку операций. Позволяет: фильтровать, сортировать, преобразовывать, агрегировать и параллельно обрабатывать данные.

Особенности: потоки не изменяют исходные данные.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Расскажите, какие шаблоны проектирования используются внутри Stream API? (Builder, Strategy, Decorator, Factory Method, Pipeline).

A
  • Builder - позволяет пошагово создавать сложные объекты, давая пользователю возможность комбинировать компоненты.
  • Strategy - обеспечивает выбор алгоритма выполнения во время работы программы.
  • Decorator - добавляет новую функциональность объекту, не изменяя его структуру.
  • Factory Method - создание потоков (Stream.of()) с использованием подклассов вместо прямого создания экземпляров.
  • Pipeline - конвейерная обработка данных через комбинацию промежуточных и терминальных операций.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Объясните, где они используются в Stream API.

A
  • Builder - создает цепочки операций (map(), filter(), sorted()) для обработки данных поэтапно.
  • Strategy - позволяет выбирать алгоритм выполнения (stream() или parallelStream()).
  • Decorator - методы filter(), map(), flatMap() и другие конвейерные операции действуют как декораторы, добавляя функциональность к потоку данных без изменения исходного источника данных.
  • Factory Method - создает потоки через методы Stream.of() и Arrays.stream().
  • Pipeline - представляет собой последовательность конвейерных операций, где каждая операция обрабатывает поток данных и передает результат следующей операции в цепочке.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Что такое конвейерные и терминальные операции?

A
  • Конвейерные операции - это промежуточные операции, которые выполняют преобразование данных и возвращают новый поток. Эти операции выполняются только после вызова терминальной операции.
  • Терминальные операции - инициируют выполнение всех промежуточных операций, возвращают результат и закрывают поток.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Перечислите конвейерные (промежуточные) методы Stream API.

A
  • filter() - фильтрует элементы потока по предикату.
  • map() - преобразует каждый элемент потока, применяя функцию.
  • flatMap() - объединяет вложенные потоки в один.
  • distinct() - удаляет дубликаты из потока.
  • sorted() - сортирует элементы потока по компаратору, по умолчанию (natural order).
  • peek() - выполняет действие для каждого элемента потока без изменения самого потока. Используется для отладки.
  • limit() - ограничивает количество элементов в потоке до заданного количества.
  • skip() - пропускает первые n элементов потока.

Дополнительные конвейерные методы для примитивных потоков:

  • mapToInt(), mapToLong(), mapToDouble() - преобразуют элементы потока в поток примитивов int, long, double.
  • flatMapToInt(), flatMapToLong(), flatMapToDouble() - преобразует элементы в поток примитивов int, long, double, затем объединяет все потоки в один.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Перечислите терминальные методы Stream API.

A
  • forEach() - выполняет действие для каждого элемента потока.
  • collect() - собирает элементы потока в коллекцию, строку или другой контейнер.
  • reduce() - выполняет агрегацию элементов, сводя их к одному результату.
  • count() - возвращает количество элементов в потоке.
  • toArray() - преобразует поток в массив.
  • min/max() - возвращает минимальный/максимальный элемент потока согласно компаратору.
  • findFirst() - возвращает первый элемент потока или Optional.empty.
  • findAny() - возвращает любой элемент потока.
  • allMatch() - проверяет, что все элементы соответствуют предикату.
  • noneMatch() - проверяет, что ни один элемент не соответствует предикату.
  • anyMatch() - проверяет, что хотя бы один элемент соответствует предикату.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Что такое отложенный выполнение lamdba?

A

Промежуточные операции потока выполняются только при вызове терминальной операции.

17
Q

Что делает метод filter()?

A

filter() - фильтрует элементы по предикату.
Промежуточная операция, возвращает новый поток с элементами, прошедшими фильтр.

18
Q

Что делает метод map()?

A

map() - преобразует каждый элемент потока, применяя функцию и возвращает новый поток с результатами преобразования.

19
Q

Что делает метод flatMap()?

A

flatMap() - объединяет вложенные потоки в один.

20
Q

Что делает метод collect?

A

collect() - собирает элементы в коллекцию, массив и другую структуру данных.

21
Q

Что делает метод findFirst?

A

findFirst() - возвращает первый элемент потока в виде Optional.

22
Q

Что делает метод reduce?

A

reduce() - агрегирует элементы потока в одно значение. Ассоциативную бинарную операцию.

Применяться для суммирования, нахождения макс, произведения чисел, конкатенации строк и других операций, которые объединяют элементы потока в одно значение.

23
Q

Что делают методы min и max?

A

min()/max() - возвращают минимальный/максимальный элемент потока по компаратору. Терминальная операция, возвращает Optional<T>.

24
Q

Что делают методы count, sum, average?

A
  • count() - возвращает количество элементов потока.
  • sum() - возвращает сумму всех элементов потока примитивных типов IntStream, LongStream или DoubleStream. Для потоков объектов, таких как Stream<Integer>, необходимо использовать mapToInt() и затем применить sum().
  • average() - вычисляет среднее значение элементов в потоке примитивных типов IntStream, LongStream или DoubleStream. Возвращает OptionalDouble.
25
Что делают методы forEach и peek?
* **forEach**() - выполняет действие для каждого элемента потока. Терминальная операция. * **peek**() - выполняет **промежуточное** действие, не изменяя поток. Используется для отладки, логирования.
26
Что делают методы skip и limit?
* **skip**() - пропускает первые n элементов в начале потока. * **limit**() - оставляет первые n элементов. Возвращает новый поток, содержащий только первые n элементов исходного потока.
27
Что делают методы allMatch(), noneMatch() и anyMatch()?
* **allMatch**() - проверяет, что все элементы соответствуют предикату. * **noneMatch**() - проверяет, что ни один элемент не соответствует предикату. * **anyMatch**() - проверяет, что хотя бы один элемент предикату. Все три метода **терминальные**, возвращающие **boolean**.
28
Что делают методы mapToInt(), flatMapToInt(), mapToObj()?
* **mapToInt**() - преобразует элементы в int и возвращает IntStream. * **flatMapToInt**() - преобразует каждый элемент потока в IntStream и объединяет все результирующие потоки в один IntStream. * **mapToObj**() - преобразует примитивный поток IntStream, LongStream, DoubleStream в **любой** объектный Stream``, используя функцию преобразования.
29
Что такое числовой поток?
Числовой поток **IntStream**, **LongStream**, **DoubleStream** - это поток для работы с примитивными типами данных **int**, **long** и **double**. Преимущества: * Не нужен autoboxing/unboxing примитивных типов. * Предоставляют методы sum(), average(), min(), max() и другие. * Меньше расход памяти.
30
Чем отличается Stream`` от IntStream``?
* **Stream**`` - поток объектов типа Integer, требуется autoboxing/unboxing, менее эффективен для чисел. * **IntStream** - поток примитивов типа int, не нужен autoboxing/unboxing, более производителен для числовых операций.
31
Что делает метод boxed?
**boxed**() - преобразует примитивный поток в соответствующий ему объектный. * **IntStream** → **Stream**`` * **LongStream** → **Stream**`` * **DoubleStream** → **Stream**``
32
Возможно ли прервать выполнение потока по аналогии с break?
Да, в следующих случаях: `1.` Раннее завершение: * **anyMatch**(), **allMatch**(), **noneMatch**() - останавливают поток при достижении результата. * **findFirst**(), **findAny**() - завершают поток после нахождения элемента. `2.` Ограничение: * **limit**() - ограничивает число обрабатываемых элементов. * **takeWhile**() - завершает поток при первом несоответствии предикату. `3.` **Исключение**: поток прерывается вручную через выброс исключения.
33
Возможно ли пропустить элемент потока по аналогии с continue?
В Stream API нет прямого аналога **continue**, но пропуск элементов возможен: * **filter**() - фильтрует элементы по предикату. * **skip**() - пропускает первые n элементов. * **takeWhile**() - завершает поток при первом несоответствии предикату.
34
Что такое Optional?
* **Optional** - это класс-обёртка для объекта, который может содержать значение или быть пустым. * Помогает избежать **NullPointerException** и предоставляет методы для обработки значений, которые могут быть пустыми.
35
Перечислите методы Optional.
* **of**() - создаёт Optional с непустым значением. * **ofNullable**() - создаёт Optional, допускающий null. * **empty**() - создаёт пустой Optional. * **isPresent**() - проверяет наличие значения. * **isEmpty**() - проверяет отсутствие значения. * **get**() - возвращает значение, если оно есть. * **orElse**() - возвращает значение или дефолтное. * **orElseGet**() - возвращает значение или результат Supplier. * **orElseThrow**() - выбрасывает исключение, если значения нет. * **ifPresent**() - выполняет действие, если значение есть. * **ifPresentOrElse**() - выполняет действие или альтернативно. * **map**() - преобразует значение применяя функцию. * **flatMap**() - преобразует значение в другой Optional, убирая вложенность `Optional>`. * **filte**r() - фильтрует элементы по предикату.
36
В чем разница между методами orElse() и orElseGet()?
* **orElse**() - всегда вычисляет и возвращает заданное значение, даже если оно не понадобится. * **orElse**() - вычисляет значение только при его необходимости, используя Supplier.
37
Расскажите про фабричные методы List.of, Set.of, Map.of?
Эти методы создают неизменяемые коллекции и не поддерживают **null**: * **List.of**() - создаёт неизменяемый список. * **Set.of**() - создаёт неизменяемое множество. * **Map.of**() - создаёт неизменяемую карту (до 10 пар ключ-значение). Для карт с более чем 10 парами существует перегрузка Map.ofEntries(). Если неизменяемая коллекция содержит **null**, выбрасывается **NullPointerException**. Попытка изменения неизменяемую коллекцию выбросит **UnsupportedOperationException**.
38
Для чего используется var?
* **var** используется для упрощения кода, позволяя компилятору определять тип переменной по типу её значения. * **var** не является ключевым словом и зарезервировано как идентификатор, поэтому нельзя использовать как название переменной, метода итд.
39
В каких случаях можно использовать var?
**var** можно использовать: * для локальных переменных. * в циклах for. * с лямбда-выражениями. **Нельзя** использовать для полей класса, параметров метода и возвращаемых значений или если тип не может быть выведен однозначно.