Predicate в Java: функциональный интерфейс и примеры - Вопросы
Всего: 5 вопросов
1. Что такое интерфейс Predicate в Java и когда он используется?
Что такое интерфейс 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 лямбда-выражение, которое проверяет, является ли число отрицательным.
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.
Методы по умолчанию (аналоги &&, || и !):
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<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()?
Нет. Внутри 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).