Функциональные интерфейсы Java

Термин функциональный интерфейс был введен в Java 8. Это интерфейс, который содержит только один абстрактный (не реализованный) метод. Может содержать стандартные и статические, которые имеют реализацию, в дополнение к одному нереализованному.

Вот пример:

public interface MyFunctionalInterface {
    public void execute();
}

Вышеуказанное содержит только один метод, и этот метод не имеет реализации.

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

public interface MyFunctionalInterface2{
    public void execute();

    public default void print(String text) {
        System.out.println(text);
    }

    public static void print(String text, PrintWriter writer) throws IOException {
        writer.write(text);
    }
}

Вышеупомянутый интерфейс все еще считается функциональным, поскольку он содержит только один не реализованный метод.

Реализация с помощью лямбда-выражения

Вот пример:

MyFunctionalInterface lambda =() -> {
    System.out.println("Executing...");
}

Лямбда-выражение реализует единственный метод из интерфейса. Чтобы узнать, какой метод реализует лямбда-выражение, интерфейс может содержать только один не реализованный метод. Другими словами, он должен быть функциональным.

Встроенные функциональные интерфейсы

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

Function

Интерфейс Function interface(java.util.function.Function) является одним из самых центральных функциональных интерфейсов. Представляет функцию (метод), которая принимает один параметр и возвращает одно значение. Вот как выглядит определение:

public interface Function {

    public  apply(T parameter);
}

Интерфейс Function на самом деле содержит несколько дополнительных методов в дополнение к методам, перечисленным выше, но, поскольку все они поставляются с реализацией по умолчанию, вам не нужно реализовывать их.

Единственный метод, который необходимо реализовать для реализации интерфейса Function, — это apply(). Вот пример реализации функции:

public class AddThree implements Function {

    @Override
    public Long apply(Long aLong) {
        return aLong + 3;
    }
}

В этой реализации функции реализован метод apply(), поэтому он принимает параметр Long в качестве параметра и возвращает Long. Вот пример использования вышеупомянутого класса AddThree:

Function adder = new AddThree();
Long result = adder.apply((long) 4);
System.out.println("result = " + result);
  1. Этот пример создает новый экземпляр AddThree и назначает его переменной Function.
  2. Вызывается метод apply() для экземпляра AddThree.
  3. Распечатывает результат (который равен 7).

Вы также можете реализовать Function с помощью лямбда-выражения:

Function adder =(value) -> value + 3;
Long resultLambda = adder.apply((long) 8);
System.out.println("resultLambda = " + resultLambda);

Как видите, реализация Function теперь встроена в объявление переменной adderLambda, а не в отдельный класс. Это немного короче, плюс мы можем видеть непосредственно в приведенном выше коде, что он делает.

Predicate

Интерфейс Java Predicate, java.util.function.Predicate, представляет простую функцию, которая принимает одно значение в качестве параметра и возвращает true или false:

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

Интерфейс Predicate содержит больше методов, чем метод test(), но остальные являются стандартными или статическими, которые вам не нужно реализовывать.

Вы можете реализовать Predicate, используя класс, например так:

public class CheckForNull implements Predicate {
    @Override
    public boolean test(Object o) {
        return o != null;
    }
}

Вы также можете реализовать Predicate, используя лямбда-выражение:

Predicate predicate =(value) -> value != null;

Эта лямбда-реализация Predicate фактически делает то же самое, что и реализация выше, использующая класс.

UnaryOperator

Интерфейс Java UnaryOperator представляет операцию, которая принимает один параметр и возвращает параметр того же типа:

UnaryOperator unaryOperator = 
      (person) -> { person.name = "New Name"; return person; };

Интерфейс UnaryOperator может использоваться для представления операции, которая принимает конкретный объект в качестве параметра, изменяет этот объект и возвращает его снова — возможно, как часть цепочки обработки функционального потока.

BinaryOperator

BinaryOperator — это функциональный интерфейс, представляющий операцию, которая принимает два параметра и возвращает одно значение. Оба параметра и тип возвращаемого значения должны быть одного типа. Полезен при реализации функций, которые суммируют, вычитают, делят, умножают и т. д. Два элемента одного типа и возвращают третий элемент того же типа.

Реализация:

BinaryOperator binaryOperator =
      (value1, value2) -> { value1.add(value2); return value1; };

Supplier

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

Supplier supplier =() -> new Integer((int)(Math.random() * 1000D));

Эта реализация Java Supplier возвращает новый экземпляр Integer со случайным значением от 0 до 1000.

Consumer

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

Consumer consumer =(value) -> System.out.println(value);

Эта реализация выводит значение, переданное ему в качестве параметра, в System.out.

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