Присудок на Java


100

Я переглядаю код, який використовується Predicateна Java. Я ніколи не використовував Predicate. Хтось може мене направляти до будь-якого навчального чи концептуального пояснення Predicateта його реалізації на Java?


4
Ви говорите про гуави Predicate? Щось подібне? Щось ще цілком?
полігенмастильні матеріали

2
Є також Apache CommonsPredicate
Dan Gravell

Відповіді:


203

Я припускаю, що ви говорите про com.google.common.base.Predicate<T>Гуаву.

З API:

Визначає значення a trueабо falseзначення для заданого входу. Наприклад, RegexPredicateможе реалізовувати Predicate<String>та повертати true для будь-якого рядка, що відповідає його заданому регулярному вираженню.

По суті це абстракція OOP для booleanтесту.

Наприклад, у вас може бути такий помічний метод:

static boolean isEven(int num) {
   return (num % 2) == 0; // simple
}

Тепер, задавши List<Integer>, ви можете обробити лише парні числа на зразок цього:

    List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    for (int number : numbers) {
        if (isEven(number)) {
            process(number);
        }
    }

З Predicate, ifтест абстрагується як тип. Це дозволяє йому взаємодіяти з рештою API, наприклад Iterables, у яких є багато корисних методів, які потрібні Predicate.

Таким чином, тепер ви можете написати щось подібне:

    Predicate<Integer> isEven = new Predicate<Integer>() {
        @Override public boolean apply(Integer number) {
            return (number % 2) == 0;
        }               
    };
    Iterable<Integer> evenNumbers = Iterables.filter(numbers, isEven);

    for (int number : evenNumbers) {
        process(number);
    }

Зауважте, що тепер цикл для кожного набагато простіший без ifтесту. Ми досягли більш високого рівня абстрагування, визначивши Iterable<Integer> evenNumbers, filterвикористовуючи -ing Predicate.

Посилання API

  • Iterables.filter
    • Повертає елементи, що задовольняють присудок.

Про функцію вищого порядку

Predicateдозволяє Iterables.filterвиконувати функцію, що називається функцією вищого порядку. Саме по собі це дає багато переваг. Візьмемо List<Integer> numbersприклад вище. Припустимо, ми хочемо перевірити, чи всі цифри позитивні. Ми можемо написати щось подібне:

static boolean isAllPositive(Iterable<Integer> numbers) {
    for (Integer number : numbers) {
        if (number < 0) {
            return false;
        }
    }
    return true;
}

//...
if (isAllPositive(numbers)) {
    System.out.println("Yep!");
}

За допомогою а Predicateта взаємодіючи з іншими бібліотеками, ми можемо замість цього написати:

Predicate<Integer> isPositive = new Predicate<Integer>() {
    @Override public boolean apply(Integer number) {
        return number > 0;
    }       
};

//...
if (Iterables.all(numbers, isPositive)) {
    System.out.println("Yep!");
}

Сподіваємось, тепер ви можете побачити значення у вищих абстракціях для підпрограм, як-от "фільтрувати всі елементи за даним предикатом", "перевірити, чи всі елементи задовольняють даному предикату" тощо.

На жаль, у Java немає першокласних методів: ви не можете передавати методи до Iterables.filterта Iterables.all. Звичайно, ви можете обходити об'єкти на Java. Таким чином, визначається Predicateтип, і ви передаєте об'єкти, що реалізують цей інтерфейс.

Дивитися також


4
Я не мав на увазі присудок Гуави, я повинен був бути чітким у своєму запитанні. Але ваше пояснення допомогло мені зрозуміти, що я шукав, як використовується логіка предиката в Java. Дякую за детальне пояснення
srikanth

@polygenelubricants, навіщо вигадувати, Predicate<Integer>коли у нас вже є F<Integer, Boolean>те саме?
Pacerier

Ви також можете це зробити в java 8 так: List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Predicate<Integer> isEven = integer -> (integer % 2) == 0; Iterable<Integer> evenNumbers = numbers.stream().filter(isEven).collect(Collectors.toList());

14

Присудок - це функція, яка повертає значення true / false (тобто булеве), на відміну від пропозиції, яке є значення true / false (тобто булеве). У Java не може бути автономних функцій, і тому створюється предикат, створюючи інтерфейс для об'єкта, який представляє предикат, а потім забезпечує клас, який реалізує цей інтерфейс. Прикладом інтерфейсу для предиката може бути:

public interface Predicate<ARGTYPE>
{
    public boolean evaluate(ARGTYPE arg);
}

І тоді у вас може бути така реалізація, як:

public class Tautology<E> implements Predicate<E>
{
     public boolean evaluate(E arg){
         return true;
     }
}

Для кращого концептуального розуміння, ви можете прочитати про логіку першого порядку.

Редагування
Існує стандартний інтерфейс предикатів ( java.util.function.Predicate ), визначений в Java API, як у Java 8. До Java 8 вам може зручно повторно використовувати інтерфейс com.google.common.base.Predicate від Гуава .

Також зауважте, що на Java 8 набагато простіше писати предикати за допомогою лямбда. Наприклад, у Java 8 і вище можна перейти p -> trueдо функції замість визначення названого підкласу Tautology, як описано вище.


0

Ви можете переглянути приклади java doc або приклад використання предиката тут

В основному він використовується для фільтрації рядків у наборі результатів на основі будь-яких конкретних критеріїв, які у вас є, і повернення правдивих для тих рядків, які відповідають вашим критеріям:

 // the age column to be between 7 and 10
    AgeFilter filter = new AgeFilter(7, 10, 3);

    // set the filter.
    resultset.beforeFirst();
    resultset.setFilter(filter);

Я посилався на загальний присудок, а не пов'язаний з результатами набору. спасибі хоч
srikanth

0

Доповнення до сказаного Мікелем :

Для фільтрації колекцій у Java ви можете використовувати предикат наступним чином:

public static <T> Collection<T> filter(final Collection<T> target,
   final Predicate<T> predicate) {
  final Collection<T> result = new ArrayList<T>();
  for (final T element : target) {
   if (predicate.apply(element)) {
    result.add(element);
   }
  }
  return result;
}

одним із можливих предикатів може бути:

final Predicate<DisplayFieldDto> filterCriteria = 
                    new Predicate<DisplayFieldDto>() {
   public boolean apply(final DisplayFieldDto displayFieldDto) {
    return displayFieldDto.isDisplay();
   }
  };

Використання:

 final List<DisplayFieldDto> filteredList=
 (List<DisplayFieldDto>)filter(displayFieldsList, filterCriteria);

1
Хіба це в основному не є поразкою мети? Основна причина вибору функціонального підходу - НЕ повторювати вручну та позбуватися від цього. Рівень абстракції стає вищим і потужнішим - однак, якщо робити це вручну, перемагає цю мету і повертається до абстракції низького рівня.
Євген
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.