Java 8 зміг зробити це, впровадивши кілька готових функціональних можливостей, серед яких Predicate є однією з них, що зробила частину коду, яка відповідає за ухвалення рішень, легкою та ефективною.
Це може стати вашою реальністю, якщо ви знайдете код ухвалення рішень, в якому вам доводиться писати вичерпні конструкції if-else. Якщо це так, Predicates можуть бути тим рефакторингом, який допоможе мати чисту та лаконічну логіку.
Наступне буде історією про те, як я перейшов від «не знаю» до «владарювання» Predicates через практичні застосування, зрозумів їхнє використання і отримав численні результати.
Що таке Predicates у Java 8?
Predicates — це функціональні інтерфейси, що знаходяться в пакеті java.util.function
.
Це уявлення функцій, що використовують одну булеву змінну.
@FunctionalInterface
public interface Predicate {
boolean test(T t);
}
Predicates — це ваші найкращі друзі, які допомагають уникнути зайвого коду та стають у пригоді щоразу, коли ви працюєте з великою кількістю рядків або перевіряєте умови для виконання певного блоку коду.
Ключові особливості Predicates
- Функціональний інтерфейс (Functional Interface): Predicates дозволяють використовувати лямбда-вирази та посилання на методи, оскільки він має лише один абстрактний метод,
boolean test(T t)
. - Зрозуміла логіка: Predicates без сумніву спростять код, розкладаючи численні вкладені оператори if на єдиний фрагмент коду, що не перевантажений і легко зрозумілий.
3.
Комбіновані операції: Для створення складних умовних виразів ви можете поєднувати Predicates різними способами за допомогою методівand()
,or()
, а такожnegate()
.
Приклади та випадки використання
Ось кілька практичних прикладів, які демонструють ефективність Predicates:
- Перевірка, чи є число парним
Predicate isEven = num -> num % 2 == 0;
System.out.println(isEven.test(4)); // true
System.out.println(isEven.test(7)); // false
- Перевірка, чи рядок починається з "A"
Predicate startsWithA = str -> str.startsWith(“A”);
System.out.println(startsWithA.test(“Apple”)); // true
System.out.println(startsWithA.test(“Banana”)); // false
- Перевірка, чи рядок порожній
Predicate isEmpty = str -> str.isEmpty();
System.out.println(isEmpty.test(“”)); // true
System.out.println(isEmpty.test(“Hello”)); // false
4.
Перевірка, чи є число додатним
Predicate isPositive = num -> num > 0;
System.out.println(isPositive.test(5)); // true
System.out.println(isPositive.test(-3)); // false
Комбінування Predicates для складної логіки
Справжня потужність Predicates проявляється, коли ви починаєте їх комбінувати.
- Комбінування за допомогою
**and()**
Predicate isEven = num -> num % 2 == 0;
Predicate greaterThan10 = num -> num > 10;
Predicate isEvenAndGreaterThan10 = isEven.and(greaterThan10);
System.out.println(isEvenAndGreaterThan10.test(12)); // true
System.out.println(isEvenAndGreaterThan10.test(7)); // false
2.
Комбінування за допомогою **or()**
Predicate startsWithA = str -> str.startsWith("A");
Predicate endsWithZ = str -> str.endsWith("Z");
Predicate startsWithAOrEndsWithZ = startsWithA.or(endsWithZ);
System.out.println(startsWithAOrEndsWithZ.test("Apple")); // true
System.out.println(startsWithAOrEndsWithZ.test("Buzz")); // true
System.out.println(startsWithAOrEndsWithZ.test("Hello")); // false
- Заперечення Predicate
Predicate isEven = num -> num % 2 == 0;
Predicate isNotEven = isEven.negate();
System.out.println(isNotEven.test(3)); // true
System.out.println(isNotEven.test(8)); // false
4.
Перевірка на паліндром
Predicate isPalindrome = str -> str.equalsIgnoreCase(new StringBuilder(str).reverse().toString());
System.out.println(isPalindrome.test("madam")); // true
System.out.println(isPalindrome.test("hello")); // false
System.out.println(isPalindrome.test("Racecar")); // true
Підводні камені при використанні Predicate
Хоча Predicates (предикати) спрощують ухвалення рішень, є кілька поширених помилок, яких слід уникати:
1. NullPointerException при використанні посилань на методи
Використання Predicate з колекціями, що містять значення null, може призвести до помилок під час виконання. Наприклад:
List categories = Arrays.asList("Culture", "Entertainment", null);
Predicate isShortWord = s -> s.length() < 4;
// Викликає NullPointerException
categories.stream().filter(isShortWord).forEach(System.out::println);
Рішення: Додайте перевірку на null у Predicate:
Predicate isShortWord = s -> Objects.nonNull(s) && s.length() < 4;
2.
Порядок з'єднання має значення
При з'єднанні Predicates (предикатів) порядок операцій може впливати на результат. Наприклад:
Predicate isNotNull = Objects::nonNull;
Predicate isGreaterThan3 = s -> s > 3;
Predicate correctOrder = isNotNull.and(isGreaterThan3);
Predicate incorrectOrder = isGreaterThan3.and(isNotNull);
System.out.println(correctOrder.test(null)); // false
System.out.println(incorrectOrder.test(null)); // NullPointerException
Підсумки
Predicates (предикати) змінили мій підхід до ухвалення рішень у коді. Вони не лише спрощують синтаксис — вони є ознакою зміни у підходах до написання логіки, орієнтованої на цілісність, повторне використання та підтримуваність. Незалежно від того, чи фільтруєте ви дані, чи реалізуєте перевірки, Predicates допоможуть вам писати чистіший і виразніший код.
Якщо ви вагались щодо початку вивчення функціонального програмування, почніть з Predicates — ви швидко оціните їх елегантність та корисність. Успіхів у кодуванні!
Перекладено з: Java 8 Predicates