1.4. FP, Lambda, Stream API Flashcards

1
Q

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

A

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

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

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

A

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

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

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

A
  1. Supplier;
  2. Consumer (BiConsumer);
  3. Predicate (BiPredicate);
  4. Function (BiFunction);
  5. UnaryOperator и BinaryOperator.
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
  1. Function: принимает один аргумент и возвращает результат.
  2. UnaryOperator: является подтипом Function и представляет операцию над одним операндом, возвращающую результат того же типа.
  3. BinaryOperator: является подтипом BiFunction и представляет операцию над двумя операндами, возвращающую результат того же типа.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

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

A

Существуют методы, которые могут принимать в качестве параметра ссылку на функциональный интерфейс или его реализацию в виде лямбда-выражения. Вместо этого, в такой метод можно передать ссылку на метод, который совпадает по сигнатуре с ожидаемым функциональным интерфейсом. То есть, по сути, может его реализовать.
Ссылка на метод выглядит так: ИмяКласса::ИмяМетода

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

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

A

Ссылка на конструктор является тем же, что и ссылка на метод, выглядит она так: ИмяКласса::new

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

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

A

Лямбда-выражение имеет доступ:
1. К полям класса объемлющего метода и может их изменять.
2. К локальным переменным объемлющего метода, но не может их изменять и эти переменные должны быть либо final, либо effectively final. В противном случае, мы получим ошибку компиляции.
3. Переменные объявленные внутри лямбда-выражения, доступны только в лямбда-выражении.

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

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

A

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

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

Что такое Stream API?

A

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

Существует 3 возможных этапа потока:
1. Фильтрация;
2. Преобразование;
3. Упрощение или аккумуляция.

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
  1. Фабричный метод,
  2. Билдер,
  3. Декоратор,
  4. Стратегия,
  5. Пайплайн.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

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

A

Декоратор используется для добавления новых функциональностей объекту, не изменяя его структуру.

Фабричный метод используется для создания объектов с использованием подклассов вместо создания экземпляров напрямую.

Стратегия позволяет выбирать алгоритм выполнения во время выполнения программы.

Шаблон Строитель используется для пошагового создания сложных объектов, позволяя пользователю выбирать и комбинировать компоненты.

Конвейер - это архитектурный шаблон, в котором данные обрабатываются последовательно несколькими компонентами, называемыми этапами конвейера.

В Stream API, конвейер представляет собой последовательность конвейерных операций, где каждая операция обрабатывает поток данных и передает результат следующей операции в цепочке.

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

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

A

Конвейерные операции промежуточные. Они применяются к потоку данных и возвращают новый поток, который можно использовать для последующих операций. Эти операции выполняются лениво, то есть не вызывают фактического вычисления до тех пор, пока не будет вызвана терминальная операция.

Терминальные операции завершают обработку потока данных и возвращают конечный результат (или нет, если операция возвращает void). После выполнения терминальной операции поток данных больше не может быть использован.

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

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

A
  • filter() - фильтрует элементы потока, возвращая только элементы, удовлетворяющие условию.
  • map() - преобразует каждый элемент потока.
  • mapToInt() - тот же map(), но возвращает поток примитивов int (также есть соответствующие mapToDouble() и mapToLong()).
  • flatMap() - трансформирует каждый объект потока в поток других объектов, то есть все элементы коллекции коллекций или потока потоков трансформирует в единый поток. (также поддерживает возврат потоков примитивов с помощью методов flatMapToInt(), flatMapToDouble(), flatMapToLong()). Может преобразовывать элементы, применяя указанную функцию к каждому элементу.
  • peek() - применяет функцию Consumer к каждому элементу потока.
  • sorted() - сортирует элементы потока по возрастанию. Возможна сортировка по убыванию при передаче соответствующего компаратора.
  • skip() - пропускает указанное число элементов с начала потока.
  • limit() - делает выборку первых элементов из родного потока в указанном количестве (отбирает элементы из потока, пока не достигнет указанного количества).
  • distinct() - убирает дубликаты из потока.
  • mapToObj() - трансформирует числовой поток в объектный.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

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

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

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

A

Отложенное выполнение (deferred execution) - это свойство лямбда выражения, которое подразумевает то, что код внутри lambda-выражения не выполняется, пока оно не вызвано.

17
Q

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

A

Метод filter() является одним из методов в Java Stream API и используется для фильтрации элементов в потоке данных на основе заданного условия. Он принимает предикат (функцию, возвращающую булево значение) и возвращает новый поток, содержащий только те элементы исходного потока, для которых предикат возвращает true.

18
Q

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

A

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

19
Q

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

A

Метод flatMap() в Java Stream API используется для преобразования элементов в потоке и объединения результатов в один поток. Он принимает функцию (или lambda-выражение), которая возвращает поток элементов, и “разглаживает” (flattens) этот поток, объединяя его элементы в один общий поток.

Различие между map() и flatMap() заключается в том, что map() возвращает поток, состоящий из элементов, полученных преобразованием каждого элемента исходного потока, в то время как flatMap() возвращает поток, объединяя элементы из каждого потока, полученного преобразованием элементов исходного потока.

20
Q

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

A

Метод collect() в Java Stream API используется для сбора элементов потока в коллекцию, массив или другую структуру данных. Он представляет конечную операцию в потоке и принимает объект типа Collector для определения, как именно собирать элементы.

21
Q

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

A

Метод findFirst() в Java Stream API используется для получения первого элемента потока. Он возвращает Optional, который может содержать либо первый элемент потока (если поток не пуст), либо пустое значение (если поток пуст).

22
Q

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

A

Метод reduce() в Java Stream API используется для свертки (reduction) элементов потока в одно единственное значение. Это может быть сумма всех элементов, конкатенация строк, нахождение максимального/минимального значения и так далее. Метод reduce() представляет собой терминальную операцию, и он принимает два параметра:

Идентичный элемент (identity): Нейтральный элемент для операции свертки. Это значение, которое будет возвращено, если поток данных пуст.

Операция свертки (accumulator): Бинарная операция, которая сочетает два элемента в один.

23
Q

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

A

Методы min() и max() в Java Stream API используются для нахождения минимального и максимального значения в потоке соответственно. Оба метода возвращают Optional, так как поток может быть пустым.

24
Q

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

A

count(): Возвращает количество элементов в потоке. Это терминальная операция.
sum(): Возвращает сумму элементов в потоке. Метод доступен для числовых типов, таких как int, long, и double. Это терминальная операция.
average(): Возвращает среднее значение элементов в потоке. Метод также доступен для числовых типов. Это терминальная операция.

25
Q

Что делают методы forEach и peek?

A

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

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

26
Q

Что делают методы skip и limit?

A

skip используется для пропуска указанного количества элементов в начале потока. Он принимает в качестве аргумента число элементов, которые нужно пропустить.

limit используется для ограничения потока указанным количеством элементов. Он принимает в качестве аргумента число элементов, которые нужно оставить.

27
Q

Что делают методы allMatch(), noneMatch() и anyMatch()?

A

allMatch(Predicate): Проверяет, соответствуют ли все элементы потока заданному условию. Возвращает true, если все элементы соответствуют условию, и false в противном случае.

noneMatch(Predicate): Проверяет, не соответствует ли ни один элемент потока заданному условию. Возвращает true, если ни один элемент не соответствует условию, и false в противном случае.

anyMatch(Predicate): Проверяет, соответствует ли хотя бы один элемент потока заданному условию. Возвращает true, если хотя бы один элемент соответствует условию, и false в противном случае.

28
Q

Что делают методы mapToInt(), flatMapToInt(), mapToObj()?

A

Методы mapToInt(), flatMapToInt() и mapToObj() являются разновидностями методов map() и flatMap() в Java Stream API и используются для преобразования элементов потока. Различия заключаются в типе результата, который они возвращают.

mapToInt() используется для преобразования элементов потока в примитивные целочисленные значения (int). Это может быть полезно, когда вы хотите работать с числовыми данными в потоке, и вы хотите избежать накладных расходов на упаковку/распаковку объектов.

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

mapToObj() используется для преобразования элементов потока в объекты другого типа. Это полезно, когда вы хотите преобразовать примитивные значения в объекты или изменить тип объектов в потоке.

29
Q

Что такое числовой поток?

A

Числовой поток (numeric stream) в Stream API представляет собой специализированный тип потока данных, предназначенный для работы с примитивными числовыми типами данных. Он введен для повышения производительности при работе с числовыми данными, такими как int, long и double.

В Java, числовые потоки предоставляются тремя основными интерфейсами:

IntStream: Предоставляет операции для работы с потоками целых чисел (int).
LongStream: Предоставляет операции для работы с потоками длинных целых чисел (long).
DoubleStream: Предоставляет операции для работы с потоками чисел с плавающей запятой (double).

30
Q

Чем отличается Stream<Integer> от IntStream<int>?

A

Stream<Integer> представляет собой обобщенный поток, который может содержать объекты любого типа, в том числе и объекты обертки для примитивных типов, такие как Integer.
В Stream<Integer> элементы потока хранятся как объекты, что может занимать больше памяти по сравнению с примитивными типами.

IntStream представляет собой специализированный поток для работы с примитивным типом int.
Он предоставляет более эффективные операции для работы с целыми числами без необходимости упаковки и распаковки в объекты обертки.

31
Q

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

A

Метод boxed() в Stream API используется для преобразования примитивного числового потока (IntStream, LongStream, DoubleStream) в соответствующий поток объектов (Stream<Integer>, Stream<Long>, Stream<Double>).

32
Q

Возможно ли прервать выполнение потока по аналогии с break?

A

В контексте Java Stream API, которое предоставляет функциональные конструкции для обработки данных в потоке, оператор break, как в циклах, не имеет непосредственного аналога. Однако, вы можете использовать различные методы для остановки обработки потока при определенных условиях.

findFirst() или findAny(): Если ваша задача заключается в поиске первого (или любого) элемента, соответствующего определенному условию, то можно использовать методы findFirst() или findAny(). Они возвращают Optional, и вы можете проверить, содержит ли он элемент.

anyMatch(): Если вам нужно просто узнать, есть ли хотя бы один элемент, соответствующий условию, вы можете использовать anyMatch().

forEach(): Вместо “прерывания” потока, вы можете использовать forEach() для выполнения действия для каждого элемента и использовать флаг или другую переменную для условного прерывания.

33
Q

Возможно ли пропустить элемент потока по аналогии с continue?

A

В Java Stream API нет прямого аналога оператора continue, как в циклах. Однако, вы можете использовать метод filter() для пропуска элементов, которые не соответствуют определенному условию. Это позволит вам “пропустить” (или, точнее, исключить) определенные элементы из потока.

34
Q

Что такое Optional?

A

Optional в Java - это контейнерный объект, который может содержать или не содержать некоторое значение. Он был введен в Java 8 в качестве части Java API для борьбы с проблемами, связанными с null-ссылками. Optional предоставляет удобный способ обработки потенциально отсутствующих значений без необходимости явной проверки на null.

35
Q

Перечислите методы Optional.

A
  1. Optional.of(value) создает Optional объект, содержащий переданное значение. Если значение null, вызывается исключение NullPointerException.
    1.1 Optional.ofNullable(value) создает Optional объект с переданным значением. Если значение null, создается пустой Optional.
  2. Optional.empty() создает пустой Optional, который не содержит значения.
  3. isPresent() возвращает true, если Optional содержит значение, и false, если он пуст.
  4. orElse(defaultValue) возвращает значение, если Optional содержит его, иначе возвращает переданное значение по умолчанию.
    4.1 orElseGet(supplier) возвращает значение, если Optional содержит его, иначе возвращает значение, полученное от переданного поставщика (Supplier).
  5. orElseThrow(exceptionSupplier) возвращает значение, если Optional содержит его, иначе выбрасывает исключение, созданное переданным поставщиком.
  6. get() возвращает значение, если Optional содержит его. Если Optional пуст, выбрасывается исключение NoSuchElementException.
  7. filter(predicate) возвращает новый Optional, содержащий значение, если оно соответствует предикату, иначе возвращает пустой Optional.
  8. map(mapper) возвращает новый Optional, содержащий результат применения функции к значению, если оно присутствует. Если Optional пуст, возвращается пустой Optional.
  9. flatMap(mapper) аналогичен map, но позволяет возвращать Optional из функции-маппера.
  10. ifPresent(consumer) выполняет переданный потребителю (Consumer) код, если Optional содержит значение.
36
Q

В чем разница между методами orElse() и orElseGet()?

A
37
Q

Расскажите про фабричные методы List.of, Set.of, Map.of?

A

List.of() Создает неизменяемый список с заданными элементами.
Set.of() Создает неизменяемое множество с заданными элементами.
Map.of() создает неизменяемую карту с парами ключ-значение.

Map.ofEntries() позволяет создать карту с более чем десятью парами ключ-значение.

38
Q

Для чего используется var?

A

Ключевое слово var в Java введено в Java 10 и используется для объявления локальных переменных с неявным (инференсивным) типом. Это означает, что компилятор Java автоматически вычисляет тип переменной на основе значения, которое ей присваивается.

Преимущества использования var:

Краткость кода: Уменьшает количество повторяемого кода за счет уменьшения явного указания типов, что может улучшить читаемость кода.

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

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

39
Q

В каких случаях можно использовать var?

A

Ключевое слово var в Java может использоваться для объявления локальных переменных в тех случаях, где тип переменной явно вытекает из контекста и может быть однозначно определен компилятором. Вот несколько типичных случаев, когда можно использовать var:

  • Инициализация при объявлении:
  • Циклы:
  • В Lambda-выражениях:
  • Возвращаемые значения методов:
  • Объявление в цепочке вызовов методов:
  • В цепочке вызовов статических методов:
  • В try-with-resources:

Важно понимать, что var не заменяет явное указание типов в тех ситуациях, где тип переменной неочевиден из контекста. Он предоставляет сокращенный и удобный синтаксис только тогда, когда тип может быть безопасно идентифицирован компилятором.

Также стоит учитывать, что использование var не рекомендуется в следующих случаях:

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