Предикати Java 8

Java 8 зміг зробити це, впровадивши кілька готових функціональних можливостей, серед яких Predicate є однією з них, що зробила частину коду, яка відповідає за ухвалення рішень, легкою та ефективною.

Це може стати вашою реальністю, якщо ви знайдете код ухвалення рішень, в якому вам доводиться писати вичерпні конструкції if-else. Якщо це так, Predicates можуть бути тим рефакторингом, який допоможе мати чисту та лаконічну логіку.

Наступне буде історією про те, як я перейшов від «не знаю» до «владарювання» Predicates через практичні застосування, зрозумів їхнє використання і отримав численні результати.

Що таке Predicates у Java 8?

Predicates — це функціональні інтерфейси, що знаходяться в пакеті java.util.function.
Це уявлення функцій, що використовують одну булеву змінну.

@FunctionalInterface  
public interface Predicate {  
 boolean test(T t);  
}

Predicates — це ваші найкращі друзі, які допомагають уникнути зайвого коду та стають у пригоді щоразу, коли ви працюєте з великою кількістю рядків або перевіряєте умови для виконання певного блоку коду.

Ключові особливості Predicates

  1. Функціональний інтерфейс (Functional Interface): Predicates дозволяють використовувати лямбда-вирази та посилання на методи, оскільки він має лише один абстрактний метод, boolean test(T t).
  2. Зрозуміла логіка: Predicates без сумніву спростять код, розкладаючи численні вкладені оператори if на єдиний фрагмент коду, що не перевантажений і легко зрозумілий.
    3.
    Комбіновані операції: Для створення складних умовних виразів ви можете поєднувати Predicates різними способами за допомогою методів and(), or(), а також negate().

Приклади та випадки використання

Ось кілька практичних прикладів, які демонструють ефективність Predicates:

  1. Перевірка, чи є число парним
Predicate isEven = num -> num % 2 == 0;  

System.out.println(isEven.test(4)); // true  
System.out.println(isEven.test(7)); // false
  1. Перевірка, чи рядок починається з "A"
Predicate startsWithA = str -> str.startsWith(“A”);  
System.out.println(startsWithA.test(“Apple”)); // true  
System.out.println(startsWithA.test(“Banana”)); // false
  1. Перевірка, чи рядок порожній
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 проявляється, коли ви починаєте їх комбінувати.

  1. Комбінування за допомогою **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
  1. Заперечення 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

Leave a Reply

Your email address will not be published. Required fields are marked *