Predicate в Java: функциональный интерфейс и примеры - Вопросы

Всего: 5 вопросов

1. 

Что такое интерфейс Predicate в Java и когда он используется?

Predicate — встроенный функциональный интерфейс из пакета java.util.function (Java 8). Его функциональный дескриптор — T -> boolean: единственный абстрактный метод boolean test(T t) принимает один аргумент и возвращает результат проверки условия. Predicate используют, когда объект нужно проверить на заданное условие и получить ответ «да/нет»: в Stream.filter(), anyMatch(), allMatch(), noneMatch(), takeWhile(), dropWhile(), а также в Collection.removeIf().

2. 

Напишите с помощью интерфейса Predicate лямбда-выражение, которое проверяет, является ли число отрицательным.

Predicate<Integer> negative = i -> i < 0;

System.out.println(negative.test(-6)); // true
System.out.println(negative.test(6));  // false
System.out.println(negative.test(0));  // false

Ноль не является отрицательным числом, поэтому третья проверка возвращает false. Для работы с примитивом без автоупаковки удобнее IntPredicate negative = i -> i < 0;.

3. 

Перечислите методы по умолчанию (default) и статические методы интерфейса Predicate.

Методы по умолчанию (аналоги &&, || и !):

default Predicate<T> and(Predicate<? super T> other)
default Predicate<T> or(Predicate<? super T> other)
default Predicate<T> negate()

Статические методы-фабрики:

static <T> Predicate<T> isEqual(Object targetRef)          // Java 8, сравнение через Objects.equals()
static <T> Predicate<T> not(Predicate<? super T> target)   // Java 11

Все они возвращают новый Predicate и не изменяют исходный. Параметр ? super T позволяет комбинировать предикат с предикатом более общего типа, например Predicate<Object>.

4. 

Чем Predicate<T> отличается от Function<T, Boolean>?

Predicate возвращает примитив boolean, а Function<T, Boolean> — объект-обёртку Boolean: появляется автоупаковка и возможен null. У Predicate есть методы and(), or(), negate() и статические isEqual(), not(), которых у Function нет. Кроме того, методы JDK Stream.filter(), anyMatch(), Collection.removeIf() объявлены с параметром типа Predicate, поэтому Function<T, Boolean> в них передать нельзя.

5. 

Вычисляются ли оба предиката при вызове and() и or()?

Нет. Внутри and() и or() используются операторы && и ||, поэтому работает короткое замыкание: в a.and(b) предикат b не вызовется, если a вернул false, а в a.or(b) — если a вернул true. Поэтому дешёвые и защитные проверки ставят первыми:

Predicate<String> notNull = Objects::nonNull;
Predicate<String> notBlank = s -> !s.isBlank();

Predicate<String> valid = notNull.and(notBlank); // проверка на null идёт первой

Обратный порядок привёл бы к NullPointerException. Отдельно учтите: a.and(null) бросает NullPointerException уже при сборке предиката, потому что реализация начинается с Objects.requireNonNull(other).

Страница 1 из 1