← Назад к вопросам
Что такое Predicate?
1.0 Junior🔥 151 комментариев
#Stream API и функциональное программирование
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Predicate в Java
Predicate — это функциональный интерфейс, который возвращает boolean значение. Используется для тестирования условий, фильтрации и проверки объектов. Введён в Java 8 как часть функционального программирования.
Определение Predicate
// Функциональный интерфейс с одним методом
@FunctionalInterface
public interface Predicate<T> {
// Основной метод
boolean test(T t);
// Дополнительные методы для комбинирования
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
}
Простые примеры
1. Базовое использование
// Predicate: проверить, является ли число чётным
Predicate<Integer> isEven = n -> n % 2 == 0;
System.out.println(isEven.test(4)); // true
System.out.println(isEven.test(5)); // false
// Predicate: проверить длину строки
Predicate<String> hasLength = s -> s.length() > 3;
System.out.println(hasLength.test("Hello")); // true
System.out.println(hasLength.test("Hi")); // false
2. Фильтрация в Stream API
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
Predicate<Integer> isEven = n -> n % 2 == 0;
// Фильтруем через Predicate
List<Integer> evenNumbers = numbers.stream()
.filter(isEven)
.collect(Collectors.toList());
// Результат: [2, 4, 6]
Комбинирование Predicates
1. Метод and()
Predicate<Integer> isEven = n -> n % 2 == 0;
Predicate<Integer> isGreaterThanFive = n -> n > 5;
// Комбинируем: чётное И больше 5
Predicate<Integer> combined = isEven.and(isGreaterThanFive);
List<Integer> numbers = Arrays.asList(1, 2, 4, 6, 8, 10);
List<Integer> result = numbers.stream()
.filter(combined)
.collect(Collectors.toList());
// Результат: [6, 8, 10]
2. Метод or()
Predicate<String> isShort = s -> s.length() < 3;
Predicate<String> startsWithA = s -> s.startsWith("A");
// ИЛИ коротко, ИЛИ начинается с A
Predicate<String> combined = isShort.or(startsWithA);
List<String> words = Arrays.asList("Hi", "Hello", "Apple", "Banana");
List<String> result = words.stream()
.filter(combined)
.collect(Collectors.toList());
// Результат: ["Hi", "Apple"]
3. Метод negate()
Predicate<Integer> isEven = n -> n % 2 == 0;
// Противоположное условие
Predicate<Integer> isOdd = isEven.negate();
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> oddNumbers = numbers.stream()
.filter(isOdd)
.collect(Collectors.toList());
// Результат: [1, 3, 5]
Практический пример: фильтрация объектов
class User {
private String name;
private int age;
private String role;
// конструктор, getters...
}
class UserFilter {
public static void main(String[] args) {
List<User> users = Arrays.asList(
new User("Alice", 25, "ADMIN"),
new User("Bob", 17, "USER"),
new User("Charlie", 30, "ADMIN"),
new User("David", 16, "USER")
);
// Predicates для разных условий
Predicate<User> isAdult = user -> user.getAge() >= 18;
Predicate<User> isAdmin = user -> "ADMIN".equals(user.getRole());
Predicate<User> nameStartsWithA = user -> user.getName().startsWith("A");
// Фильтруем: взрослые админы
List<User> adminAdults = users.stream()
.filter(isAdmin.and(isAdult))
.collect(Collectors.toList());
// Результат: Alice, Charlie
// Фильтруем: админы ИЛИ имя начинается на A
List<User> filtered = users.stream()
.filter(isAdmin.or(nameStartsWithA))
.collect(Collectors.toList());
// Результат: Alice, Charlie
// Фильтруем: НЕ взрослые
List<User> minors = users.stream()
.filter(isAdult.negate())
.collect(Collectors.toList());
// Результат: Bob, David
}
}
Создание пользовательских методов с Predicate
class NumberUtils {
// Метод, принимающий Predicate
public static int countMatching(List<Integer> numbers, Predicate<Integer> predicate) {
return (int) numbers.stream()
.filter(predicate)
.count();
}
// Использование
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int evenCount = countMatching(numbers, n -> n % 2 == 0);
int largeCount = countMatching(numbers, n -> n > 5);
System.out.println("Even: " + evenCount); // 5
System.out.println("Large: " + largeCount); // 5
}
}
Predicate vs Function
// Function<T, R> — преобразует T в R
Function<String, Integer> stringToLength = s -> s.length();
Integer length = stringToLength.apply("Hello"); // 5
// Predicate<T> — тестирует T, возвращает boolean
Predicate<String> isLong = s -> s.length() > 3;
boolean result = isLong.test("Hello"); // true
Predicate в JPA/Hibernate
// Spring Data JPA с Predicate
public interface UserRepository extends
JpaRepository<User, Long>,
QuerydslPredicateExecutor<User> { // Важно!
}
// Использование в сервисе
@Service
public class UserService {
@Autowired
private UserRepository repository;
public List<User> findAdminUsers() {
Predicate predicate = QUser.user
.role.eq("ADMIN")
.and(QUser.user.age.gt(18));
return (List<User>) repository.findAll(predicate);
}
}
Когда использовать Predicate
✅ Используй Predicate:
- Фильтрация коллекций (stream().filter())
- Условные проверки (if, while)
- Передача условий в методы
- Создание переиспользуемых условий
❌ Не используй, если:
- Нужно преобразовать объект (используй Function)
- Нужен результат другого типа (используй Function)
Заключение
Predicate — это мощный инструмент функционального программирования, который делает код:
- Читаемым — ясно видны условия
- Переиспользуемым — можно комбинировать predicates
- Декларативным — что ты хочешь, а не как это сделать
- Кратким — lambda выражения вместо анонимных классов