Core-2: Functional Flashcards

1
Q

Что такое «лямбда»?

A

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

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

interface Operationable {
    int calculate(int x, int y);
}

public static void main(String[] args) {
    Operationable operation = (x, y) -> x + y;     
    int result = operation.calculate(10, 20);
		Operationable operation2 = (x, y) -> x * y;     
    int result2 = operation2.calculate(10, 20);
    System.out.println(result); //30
		System.out.println(result); //200
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

К каким переменным есть доступ у лямбда-выражений?

A

Доступ к переменным внешней области действия из лямбда-выражения очень схож к доступу из анонимных объектов. Можно ссылаться на:

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

Как отсортировать список строк с помощью лямбда-выражения?

A
public static List<String> sort(List<String> list){
    Collections.sort(list, (a, b) -> a.compareTo(b));
    return list;
		OR:
	list.sort(String::compareTo);
    return list;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

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

A

method reference: сокращение лямбды, которая содержит лишь один вызов метода.

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

private interface Measurable {
public int length(String string);
}
public static void main(String[] args) {
Measurable a = String::length;
System.out.println(a.length(“abc”));
}

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

4 типа ссылки на метод

A

Есть 4 вида:
1) на статический метод любого:
x -> Class.staticMethod(x)
=> Class::staticMethod

2) на метод класса, которому принадлежит обрабатываемый объект:
(obj, args) -> obj.instanceMethod(args)
=> ObjectType::instanceMethod

3) на метод для экземпляра класса:
(obj, args) -> obj.instanceMethod(args)
=> obj::instanceMethod

4) на конструктор:
(args) -> new ClassName(args)
=> ClassName::new

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

Что выбрать: Lambda VS MethodRef.

A

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

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

Объясните выражение System.out::println

A

Данное выражение иллюстрирует механизм instance method reference: передачи ссылки на метод println() статического поля out класса System.

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

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

A

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

Чтобы точно определить интерфейс как функциональный, добавлена аннотация @FunctionalInterface, работающая по принципу @Override. Она обозначит замысел и не даст определить второй абстрактный метод в интерфейсе.

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

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

Для чего нужен функциональный интерфейс Function<T,R>?

A

Function<T, R> - интерфейс, с помощью которого реализуется функция, получающая на вход экземпляр класса T и возвращающая на выходе экземпляр класса R.

Методы по умолчанию могут использоваться для построения цепочек вызовов (compose, andThen).

Function<String, Integer> toInteger = Integer::valueOf;
Function<String, String> backToString = toInteger.andThen(String::valueOf);
backToString.apply("123");
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Для чего нужны функциональные интерфейсы ` DoubleFunction<R>, IntFunction<R> и LongFunction<R>?`</R></R></R>

A
  • DoubleFunction<R> - функция, получающая на вход Double и возвращающая на выходе экземпляр класса R;
    - IntFunction<R> - функция, получающая на вход Integer и возвращающая на выходе экземпляр класса R;
  • LongFunction<R> - функция, получающая на вход Long и возвращающая на выходе экземпляр класса R.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

разобрать (compose, andThen) в Function

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

Для чего нужны функциональные интерфейсы UnaryOperator<T>, DoubleUnaryOperator, IntUnaryOperator и LongUnaryOperator?

A

UnaryOperator<T> (унарный оператор) принимает в качестве параметра объект типа T, выполняет над ними операции и возвращает результат операций в виде объекта типа T:

UnaryOperator<Integer> operator = x -> x * x;
System.out.println(operator.apply(5)); // 25
  • DoubleUnaryOperator - унарный оператор, получающий на вход Double;
  • IntUnaryOperator - унарный оператор, получающий на вход Integer;
  • LongUnaryOperator - унарный оператор, получающий на вход Long.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Для чего нужны функциональные интерфейсы BinaryOperator<T>, DoubleBinaryOperator, IntBinaryOperator и LongBinaryOperator?</T>

A

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

BinaryOperator<Integer> operator = (a, b) -> a + b;
System.out.println(operator.apply(1, 2)); // 3
  • DoubleBinaryOperator - бинарный оператор, получающий на вход Double;
  • IntBinaryOperator - бинарный оператор, получающий на вход Integer;
  • LongBinaryOperator - бинарный оператор, получающий на вход Long.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Для чего нужны функциональные интерфейсы Predicate<T>, DoublePredicate, IntPredicate и LongPredicate?</T>

A

Predicate<T> (предикат) - интерфейс, с помощью которого реализуется функция, получающая на вход экземпляр класса T и возвращающая на выходе значение типа boolean.

Интерфейс содержит различные методы по умолчанию, позволяющие строить сложные условия (and, or, negate).

Predicate<String> predicate = (s) -> s.length() > 0;
predicate.test("foo"); // true
predicate.negate().test("foo"); // false
  • DoublePredicate - предикат, получающий на вход Double;
  • IntPredicate - предикат, получающий на вход Integer;
  • LongPredicate - предикат, получающий на вход Long.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Дефолтные Методы Predicate

A
- default Predicate<T> and(Predicate<? super T> other)

- default Predicate<T> negate() {
        return (t) -> !test(t);
    }
		
-  default Predicate<T> or(Predicate<? super T> other)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Для чего нужны функциональные интерфейсы Consumer<T>, DoubleConsumer, IntConsumer и LongConsumer?

A

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

Consumer<String> hello = (name) -> System.out.println("Hello, " + name);
hello.accept("world");

имеет дефолтный метод:
default Consumer<T> andThen(Consumer<? super T> after)

DoubleConsumer - потребитель, получающий на вход Double;
IntConsumer - потребитель, получающий на вход Integer;
LongConsumer - потребитель, получающий на вход Long.

17
Q

Для чего нужны функциональные интерфейсы Supplier<T>, BooleanSupplier, DoubleSupplier, IntSupplier и LongSupplier?

A

Supplier<T> (поставщик) - интерфейс, с помощью которого реализуется функция, ничего не принимающая на вход, но возвращающая на выход результат класса T;

Supplier<LocalDateTime> now = LocalDateTime::now;
now.get();

DoubleSupplier - поставщик, возвращающий Double;
IntSupplier - поставщик, возвращающий Integer;
LongSupplier - поставщик, возвращающий Long.

18
Q

Для чего нужен функциональный интерфейс BiConsumer<T,U>?

A

BiConsumer<T,U> представляет собой операцию, которая принимает два аргумента классов T и U производит с ними некоторое действие и ничего не возвращает.

19
Q

Для чего нужен функциональный интерфейс BiFunction<T,U,R>?

A

BiFunction<T,U,R> представляет собой операцию, которая принимает два аргумента классов T и U и возвращающая результат класса R.

20
Q

Для чего нужен функциональный интерфейс BiPredicate<T,U>?

A

BiPredicate<T,U> представляет собой операцию, которая принимает два аргумента классов T и U и возвращающая результат типа boolean.

21
Q

Для чего нужны функциональные интерфейсы вида _To_Function?

A

DoubleToIntFunction - операция, принимающая аргумент класса Double и возвращающая результат типа Integer;
DoubleToLongFunction - операция, принимающая аргумент класса Double и возвращающая результат типа Long;
IntToDoubleFunction - операция, принимающая аргумент класса Integer и возвращающая результат типа Double;
IntToLongFunction - операция, принимающая аргумент класса Integer и возвращающая результат типа Long;
LongToDoubleFunction - операция, принимающая аргумент класса Long и возвращающая результат типа Double;
LongToIntFunction - операция, принимающая аргумент класса Long и возвращающая результат типа Integer.

22
Q

Для чего нужны функциональные интерфейсы ToDoubleBiFunction<T,U>, ToIntBiFunction<T,U> и ToLongBiFunction<T,U>?

A

ToDoubleBiFunction<T,U> - операция принимающая два аргумента классов T и U и возвращающая результат типа Double;
ToLongBiFunction<T,U> - операция принимающая два аргумента классов T и U и возвращающая результат типа Long;
ToIntBiFunction<T,U> - операция принимающая два аргумента классов T и U и возвращающая результат типа Integer.

23
Q

Для чего нужны функциональные интерфейсы ToDoubleFunction<T>, ToIntFunction<T> и ToLongFunction<T>?

A

ToDoubleFunction<T> - операция, принимающая аргумент класса T и возвращающая результат типа Double;
ToLongFunction<T> - операция, принимающая аргумент класса T и возвращающая результат типа Long;
ToIntFunction<T> - операция, принимающая аргумент класса T и возвращающая результат типа Integer.

24
Q

Для чего нужны функциональные интерфейсы ObjDoubleConsumer<T>, ObjIntConsumer<T> и ObjLongConsumer<T>?

A

ObjDoubleConsumer<T> - операция, которая принимает два аргумента классов T и Double, производит с ними некоторое действие и ничего не возвращает;
ObjLongConsumer<T> - операция, которая принимает два аргумента классов T и Long, производит с ними некоторое действие и ничего не возвращает;
ObjIntConsumer<T> - операция, которая принимает два аргумента классов T и Integer, производит с ними некоторое действие и ничего не возвращает.