Java function and predicate

Java 8 java.util.function.Predicate tutorial with examples

This tutorial explains the functional interface Predicate which has been newly introduced in the java.util.function package. It describes Predicate’s usage with the help of multiple examples.

What is java.util.function.Predicate – Predicate is a new functional interface Click to read tutorial on Functional Interfaces defined in java.util.function package which can be used in all the contexts where an object needs to be evaluated for a given test condition and a boolean value needs to be returned based on whether the condition was successfully met or not.
Since Predicate is a functional interface, hence it can be used as the assignment target for a lambda expression Click to read Lambda Expressions tutorial or a method reference Click to read tutorial on Method References .

Advantage of predefined java.util.function.Predicate – Wherever an object needs to be evaluated and a boolean value needs to be returned( or a boolean-valued Predicate exists – in mathematical terms) the Predicate functional interface can be used. The user need not define his/her own predicate-type functional interface.

package java.util.function; import java.util.Objects; @FunctionalInterface public interface Predicate < boolean test(T t); //rest of the code goes here >
  • boolean test(T t) is the abstract method which will define the signature of the lambda expression/method reference which can be assigned to a target of type Predicate .
  • T is the type of input to the predicate
  • boolean test(T t) returns true if the input argument matches the predicate(the test condition), otherwise returns false
  • There are 3 default methods & 1 static method in Predicate which I will explain in below sections of this tutorial.
Читайте также:  Php вернуть код ошибки 404

Example of using Predicate for a boolean condition check –

import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; public class PredicateFunctionExample < public static void main(String args[])< Predicatepositive = i -> i > 0; List integerList = Arrays.asList( new Integer(1),new Integer(10), new Integer(200),new Integer(101), new Integer(-10),new Integer(0)); List filteredList = filterList(integerList, positive); filteredList.forEach(System.out::println); > public static List filterList(List listOfIntegers, Predicate predicate) < ListfilteredList = new ArrayList(); for(Integer integer:listOfIntegers) < if(predicate.test(integer))< filteredList.add(integer); >> return filteredList; > >
  • The static method filterList() takes two inputs –
    • A List of Integers which need to be filtered based on some condition
    • An instance of Predicate interface which is the condition for evaluation of each integer passed in the Integer list.

    Default methods in java.util.function.Predicate : There a few default methods also provided in the Predicate functional interface which enable us to do various types of boolean operations such as and, or, not(negate) with different instances of Predicate. These default methods are –

    Default Method Name Explanation
    and() It does logical AND of the predicate on which it is called with another predicate. Example: predicate1.and(predicate2)
    or() It does logical OR of the predicate on which it is called with another predicate. Example: predicate1.or(predicate2)
    negate() It does boolean negation of the predicate on which it is invoked. Example: predicate1.negate()
    Where, predicate1 & predicate2 are instances of Predicate interface/lambda expression/method references

    Lets say we have the same code as used above for the filterList() method. I.e. filterList will filter the input Integers List based on the predicate passed to it.
    What we are going to change is we will pass different predicates ANDed, ORed, Negated using the default methods and see the resultant output in the table below
    (Note – I am assuming that all readers are aware of AND/ OR/ NOT operations in boolean logic)

    Predicate passed Values in filteredList Explanation
    Lets say values in input IntegerList are – [-10, 0, 1, 20, 101, 200]
    (i->i>0).and(i->i>10) [20,101,200] Conditions for i greater than 0 and i greater than 10 leaves us with 3 filtered values 20,100 & 200.
    (i->i>0).or(i->i>10) [1,20,101,200] Either i is greater than 0 or i > 10 gives us 4 filtered values 1,20,101 & 200.
    (i->i>0).negate() [-10,0] Negation of i greater than zero implies i is less than or equal to 0. This gives us 2 values -10 & 0

    Static method isEqual() – Predicate interface also has a static method isEqual() which can be used to compare 2 instances of Predicate functional interface.
    Its defined as – static Predicate isEqual(Object targetRef)
    It returns a predicate that tests if two arguments are equal according to Objects.equals(Object, Object) .

    Summary – We looked at what is java.util.function.Predicate functional interface, what is the advantage of having this interface, we looked at the source including the abstract method, then we looked at the default methods, saw examples of their usages and finally learned about the static method present in the Predicate Interface.

    Источник

    Функциональные интерфейсы в Java 8 → Consumer, Supplier, Predicate и Function. Что к чему и зачем нужны

    Java представила поддержку функционального программирования в выпуске Java версии 8. Этот конкретный выпуск также представил несколько новых концепций, в частности лямбда-выражения, ссылки на методы и множество функциональных интерфейсов. При обсуждении последних, есть несколько функциональных интерфейсов, а именно Потребитель (Consumer), Поставщик (Supplier), Предикат (Predicat) и Функция (Function), которые являются наиболее важными. В этой статье мы о них и поговорим.

    Consumer (потребитель)

    Consumer — это функциональный интерфейс, который принимает один параметр на вход и не возвращает никаких выходных данных. На языке непрофессионала, как следует из названия, реализация этого интерфейса потребляет вводимые данные. Пользовательский интерфейс имеет два метода:

    void accept(T t); default Consumer andThen(Consumer after);

    Метод accept является единым абстрактным методом (SAM), который принимает один аргумент типа T. Тогда как другой метод andThen является методом по умолчанию и используется для композиции.

    Ниже приведен пример интерфейса consumer. Мы создали потребительскую реализацию, которая использует строку, а затем просто выводит ее на экран. Метод forEach принимает реализацию потребительского интерфейса.

    public void whenNamesPresentConsumeAll() < ConsumerprintConsumer = t -> System.out.println(t); Stream cities = Stream.of("Sydney", "Dhaka", "New York", "London"); cities.forEach(printConsumer); >

    В следующем примере демонстрируется использование составления нескольких реализаций интерфейса consumer для создания цепочки потребителей.
    Ниже мы создали двух потребителей: один преобразует список элементов в строки верхнего регистра, а другой выводит строку верхнего регистра.

    public void whenNamesPresentUseBothConsumer() < Listcities = Arrays.asList("Sydney", "Dhaka", "London"); Consumer upperCaseConsumer = list -> < for(int i=0; i< list.size(); i++)< list.set(i, list.get(i).toUpperCase()); >>; Consumer printConsumer = list -> list.stream() .forEach(System.out::println); upperCaseConsumer.andThen(printConsumer).accept(cities); >

    Интерфейс Consumer имеет специфические типы реализаций для типов integer, double и long -> IntConsumer, DoubleConsumer и LongConsumer, как показано ниже:

    IntConsumer void accept(int x); DoubleConsumer void accept(double x); LongConsumer void accept(long x);

    Supplier (поставщик)

    Supplier — это простой интерфейс, указывающий, что данная реализация является поставщиком какого то результа. Этот интерфейс, однако, не накладывает никаких дополнительных ограничений, которые реализация поставщика должна возвращать при каждом новом получении результата.

    У поставщика есть только один метод get() и нет никаких других методов по умолчанию или статических методов.

    public void supplier() < SupplierdoubleSupplier1 = () -> Math.random(); DoubleSupplier doubleSupplier2 = Math::random; System.out.println(doubleSupplier1.get()); System.out.println(doubleSupplier2.getAsDouble()); >

    Интерфейс поставщик имеет свои примитивные варианты, такие как IntSupplier, DoubleSupplier и т. д., как показано ниже. Обратите внимание, что имя метода — get() используется для универсального интерфейса поставщика. Однако для примитивных вариантов этот метод соответствует примитивному типу.

    IntSupplier int getAsInt(); DoubleSupplier double getAsDouble(); LongSupplier long getAsLong(); BooleanSupplier boolean getAsBoolean();

    Одно из основных применений этого интерфейса это использование для включения отложенного выполнения. Это означает отсрочку выполнения до тех пор, пока оно не понадобится. Например, в классе Optional есть метод orElseGet. Этот метод срабатывает, если у option нет данных. Это показано ниже:

    public void supplierWithOptional() < SupplierdoubleSupplier = () -> Math.random(); Optional optionalDouble = Optional.empty(); System.out.println(optionalDouble.orElseGet(doubleSupplier)); >

    Predicate (предикат)

    Интерфейс Predicate представляет собой логическую функцию аргумента. Он в основном используется для фильтрации данных из потока (stream) Java. Метод фильтра потока принимает предикат для фильтрации данных и возврата нового потока, удовлетворяющего предикату. У предиката есть метод test(), который принимает аргумент и возвращает логическое значение.

    public void testPredicate() < Listnames = Arrays.asList("Smith", "Samueal", "Catley", "Sie"); Predicate nameStartsWithS = str -> str.startsWith("S"); names.stream().filter(nameStartsWithS).forEach(System.out::println); >

    В приведенном выше примере мы создали предикат, который проверяет имена, начинающиеся с S. Этот предикат передается потоку.

    Predicate также предоставляет несколько стандартных и статических методов для композиции и других целей:

    default Predicate and(Predicate other); default Predicate or(Predicate other); static Predicate isEquals(Object targetRef); default Predicate negate();

    В следующем примере демонстрируется использование и метод для составления цепочки предикатов.

    public void testPredicateAndComposition() < Listnames = Arrays.asList("Smith", "Samueal", "Catley", "Sie"); Predicate startPredicate = str -> str.startsWith("S"); Predicate lengthPredicate = str -> str.length() >= 5; names.stream() .filter(startPredicate.and(lengthPredicate)) .forEach(System.out::println); >

    Function (функция)

    Интерфейс Function — это более общий интерфейс, который принимает один аргумент и выдает результат. В нем применяется единый абстрактный метод (SAM), который принимает аргумент типа T и выдает результат типа R. Одним из распространенных вариантов использования этого интерфейса является метод Stream.map. Пример использования показан ниже:

    public void testFunctions() < Listnames = Arrays.asList("Smith", "Gourav", "John", "Catania"); Function nameMappingFunction = String::length; List nameLength = names.stream() .map(nameMappingFunction).collect(Collectors.toList()); System.out.println(nameLength); >

    Подведем итоги

    Введение функционального программирования представило новую парадигму языка Java. И интерфейсы Consumer, Supplier, Predicate и Function играют решающую роль в том, как это реализовано в Java. Освоение этих интерфейсов и связанных с ними примитивных вариантов, безусловно, помогает писать более качественный функциональный код.

    Источник

Оцените статью