16 java 8 Flashcards

1
Q

Что такое реализация по-умолчанию в интерфейсах?

A

Метод, реализованный в интерфейсе, называется методом по умолчанию и обозначается ключевым словом default. Если класс реализует интерфейс, он наследует реализацию по умолчанию.

Метод по умолчанию - это обычный метод без модификаторов, который помечается ключевым словом default. Затем в классе нам необязательно этот метод реализовать, хотя мы можем его и переопределить
default void methodName () {/ * body * /}
Важные моменты о методах интерфейса Java по умолчанию:
- Методы интерфейса Java по умолчанию помогут нам в расширении интерфейсов, не боясь нарушать классы реализации.
- Методы по умолчанию для интерфейса Java позволяют устранить различия между интерфейсами и абстрактными классами.
- Методы по умолчанию интерфейса Java 8 помогут нам избежать использования служебных классов, например, все методы класса Collections могут быть предоставлены в самих интерфейсах.
- Методы интерфейса Java по умолчанию помогут нам в удалении базовых классов реализации, мы можем предоставить реализацию по умолчанию, и классы реализации могут выбрать, какой из них переопределить.
- Одной из основных причин введения методов по умолчанию в интерфейсах является усовершенствование API коллекций в Java 8 для поддержки лямбда-выражений.
- Если какой-либо класс в иерархии имеет метод с такой же сигнатурой, то методы по умолчанию становятся неактуальными.
- Метод по умолчанию не может переопределить метод из java.lang.Object. Рассуждения очень просты, потому что Object является базовым классом для всех классов Java. Таким образом, даже если у нас есть методы класса Object, определенные как методы по умолчанию в интерфейсах, это будет бесполезно, потому что метод класса Object всегда будет использоваться. Вот почему во избежание путаницы у нас не может быть методов по умолчанию, которые переопределяют методы класса Object.
- Методы интерфейса Java по умолчанию также называются методами защитника или методами виртуального расширения.

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

Что такое лямбда-выражения?

A

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

Лямбда-выражение - специальный синтаксис для определения функциональных объектов.

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

Лямбда-выражение не выполняется само по себе, а образует реализацию метода, определенного в функциональном интерфейсе.
При этом важно, что функциональный интерфейс должен содержать только один единственный абстрактный метод.
interface Operationable {
int calculate(int x, int y);
}
Operationable operation = (x, y) -> x + y;
Параметры лямбда-выражения должны соответствовать по тип параметрам метода из функционального интерфейса. При написании самого лямбда-выражения тип параметров писать необязательно.

Лямбда-выражение может использовать переменные, которые объявлены во вне в более общей области видимости - на уровне класса или метода, в котором лямбда-выражение определено. Однако в зависимости от того, как и где определены переменные, могут различаться способы их использования в лямбдах.
Переменные объявленные на уровне класса, мы можем получить и даже изменить. в лямбда-выражении.
Локальные переменные уровня метода мы также может использовать в лямбдах, но изменять их значение мы уже не сможем. Если мы попробуем это сделать, то среда разработки может нам высветить ошибку и то, что такую переменную надо пометить с помощью ключевого слова final, то есть сделать константой: final int n=70;. Однако это необязательно.

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

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

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

A

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

Основное назначение – использование в лямбда выражениях и method reference.
Ссылки на методы (Method References) – это компактные лямбда выражения для методов у которых уже есть имя. Например: Consumer consumer = System.out::println;

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

Но оказывается есть один тонкий момент, описанный в Java Language Specification: что функциональные интерфейсы могут содержать дополнительно абстрактные методы, определенные в классе Object.

@FunctionalInterface
public interface Comparator {
int compare(T o1, T o2);
boolean equals(Object obj);
// другие default или static методы
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Расскажите про интерфейс Predicate?

A

Predicate встроенный обобщенный функциональный интерфейс, добавленный в Java SE 8 в пакет java.util.function., который принимает на вход значение, проверяет состояние и возвращает boolean значение в качестве результата.
T -> boolean
Predicate интерфейс содержит методы по умолчанию:

default Predicate and(Predicate super T> other);
default Predicate or(Predicate super T> other);
default Predicate negate();
static Predicate isEqual(Object targetRef);

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

Расскажите про интерфейс Function?

A

Function - это встроенный обобщенный функциональный интерфейс, добавленный в Java SE 8 в пакет java.util.function.

Принимает значение в качестве аргумента одного типа и возвращает другое значение. Часто используется для преобразования одного значения в другое:

@FunctionalInterface
public interface Function {
R apply(T t);
}
T -> R
Методы по умолчанию интерфейса Function:

default Function andThen(Function super R, ? extends V> after);
default Function compose(Function super V, ? extends T> before);

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

Расскажите про интерфейс Supplier?

A

Интерфейс Supplier используется тогда, когда на вход не передаются значения, но необходимо вернуть результат.

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

@FunctionalInterface
public interface Supplier {
T get();
}

() -> T

Supplier personSupplier = Person::new;
Person person = personSupplier.get();

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

Расскажите про интерфейс Consumer?

A

Consumer - Принимает значение в качестве аргумента и ничего не возвращает:
Потребители (consumers) представляют собой операции, которые производятся над одним входным
аргументом.

@FunctionalInterface
public interface Consumer {
void accept(T t);
}
Consumer интерфейс используется в случае, если необходимо передать объект на вход и произвести над ним некоторые операции не возвращая результат. Самый частый случай использования этого интерфейса - это вывод на консоль.
T -> void
Consumer интерфейс содержит метод по умолчанию, который возвращает составной Consumer, выполняющий последовательно действия указанные в каждом интерфейсе:

default Consumer andThen(Consumer super T> after)

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

Расскажите про интерфейс Comparator?

A

интерфейс Comparator позволяет сравнивать между собой два объекта. На выходе метод возвращает значение 0, если объекты равны, положительное значение или отрицательное значение, если объекты не тождественны.
Comparator comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);
Person p1 = new Person(“John”, “Doe”);
Person p2 = new Person(“Alice”, “Wonderland”);
comparator.compare(p1, p2); // > 0
comparator.reversed().compare(p1, p2); // < 0

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

Что такое Stream?

A

Stream последовательность элементов, над которой можно производить различные операции.

Операции над потоками бывают или промежуточными (intermediate) или конечными (terminal). Конечные операции возвращают результат определенного типа, а промежуточные операции возвращают тот же поток. Таким образом вы можете строить цепочки из несколько операций над одним и тем же потоком.
Поток создаются на основе источников, например типов, реализующих java.util.Collection, такие как списки или множества (ассоциативные массивы не поддерживаются). Операции над потоками могут выполняться как последовательно, так и параллельно.
Filter

Операция Filter принимает предикат, который фильтрует все элементы потока. Эта операция является промежуточной, т.е. позволяет нам вызвать другую операцию (например, forEach) над результатом. ForEach принимает функцию, которая вызывается для каждого элемента в (уже отфильтрованном) поток. ForEach является конечной операцией. Она не возращает никакого значения, поэтому дальнейший вызов потоковых операций невозможен.

stringCollection
.stream()
.filter((s) -> s.startsWith(“a”))
.forEach(System.out::println);

// “aaa2”, “aaa1”

Sorted

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

stringCollection
.stream()
.sorted()
.filter((s) -> s.startsWith("a"))
.forEach(System.out::println);

// “aaa1”, “aaa2”

Помните, что sorted создает всего лишь отсортированное представление и не влияет на порядок элементов в исходной коллекции. Порядок строк в stringCollection остается нетронутым:

System.out.println(stringCollection);
// ddd2, aaa2, bbb1, aaa1, bbb3, ccc, bbb2, ddd1

Map

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

stringCollection
.stream()
.map(String::toUpperCase)
.sorted((a, b) -> b.compareTo(a))
.forEach(System.out::println);

// “DDD2”, “DDD1”, “CCC”, “BBB3”, “BBB2”, “AAA2”, “AAA1”

Match

Для проверки, удовлетворяет ли поток заданному предикату, используются различные операции сопоставления (match). Все операции сопоставления являются конечными и возвращают результат типа boolean.

boolean anyStartsWithA =
stringCollection
.stream()
.anyMatch((s) -> s.startsWith(“a”));

System.out.println(anyStartsWithA); // true

boolean allStartsWithA =
stringCollection
.stream()
.allMatch((s) -> s.startsWith(“a”));

System.out.println(allStartsWithA); // false

boolean noneStartsWithZ =
stringCollection
.stream()
.noneMatch((s) -> s.startsWith(“z”));

System.out.println(noneStartsWithZ); // true

Count

Операция Count является конечной операцией и возвращает количество элементов в потоке. Типом возвращаемого значения является long.

long startsWithB =
stringCollection
.stream()
.filter((s) -> s.startsWith("b"))
.count();

System.out.println(startsWithB); // 3

Reduce

Эта конечная операция производит свертку элементов потока по заданной функции. Результатом является опциональное значение.

Optional reduced =
stringCollection
.stream()
.sorted()
.reduce((s1, s2) -> s1 + "#" + s2);
reduced.ifPresent(System.out::println);
// "aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2"
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Что такое parallelStream?

A

Параллельные потоки

Как уже упоминалось выше, потоки могут быть последовательными и параллельными. Операции над последовательными потоками выполняются в одном потоке процессора, над параллельными — используя несколько потоков процессора.

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