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

User Rating: 5 / 5

Друзья, всем привет.

Сегодняшняя статья будет короткой, в ней мы поговорим о функциональном интерфейсе UnaryOperator<T>, доступном в Java, начиная с версии 1.8.

Этот функциональный интерфейс является наследником интерфейса Function<T, R>, который мы уже разбирали ранее в рамках отдельной статьи.

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

К распространённым унарным операторам относятся, например, операции инкремента (++) и декремента (--):

int i = 0;
i++; // оператор инкремента, результат его выполнения - значение локальной переменной i будет увеличино на единицу
System.out.println("i = " + i);  // вывод в консоль: i = 1

int j = 10;
j--; // оператор декремента, результат его выполнения - значение локальной переменной j будет уменьшено на единицу
System.out.println("j = " + j);  // вывод в консоль: j = 9

У интерфейса UnaryOperator<T> есть единственный параметр типа - T, который задаёт тип входного аргумента и одновременно тип результата самой унарной операции.

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

Рассмотрим небольшой пример программы на Java для демонстрации работы с функциональным интерфейсом UnaryOperator<T>:

package ru.allineed.samples.functional_interface.unaryoperator;

import ru.allineed.samples.common.OutputUtils;

import java.util.Arrays;
import java.util.List;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;

public class UnaryOperatorExample {

    public static void main(String[] args) {
        OutputUtils.printSampleTitle(
                "Функциональный интерфейс UnaryOperator в Java",
                "Functional interface UnaryOperator in Java",
                "https://allineed.ru/development/java-development/TODO");

        showIntegerIncrementDemo();
        showGreeterDemo();
    }
    
    private static void showGreeterDemo() {
        UnaryOperator<String> greeter = e -> "Привет, " + e + "!";

        List<String> people = Arrays.asList("Александр", "Иван", "Пётр", "Михаил");
        System.out.println(people.stream().map(greeter).collect(Collectors.toList()));
    }
    
    private static void showIntegerIncrementDemo() {
        UnaryOperator<Integer> increment = e -> e + 1;

        List<Integer> numbers = Arrays.asList(2, 3, -5);

        System.out.println(increment.apply(3));

        // [RU] Использование интерфейса UnaryOperator в виде готовой переменной 'increment' внутри метода Stream#map
        // [EN] Using UnaryOperator interface as a predefined variable 'increment' inside method Stream#map        
        System.out.println(numbers.stream().map(increment).collect(Collectors.toList()));

        // [RU] Использование интерфейса UnaryOperator в виде лямбда-выражения внутри метода Stream#map
        // [EN] Using UnaryOperator interface as lambda expression inside method Stream#map
        System.out.println(numbers.stream().map(e -> e + 1).collect(Collectors.toList()));
    }
}

Как видим, в главном методе main() нашего примера мы вызываем два отдельных метода:

  • showIntegerIncrementDemo - демонстрирует работу унарного оператора, реализующего операцию инкремента с целыми числами
  • showGreeterDemo - демонстрирует работу унарного оператора на строках - оператор добавляет приветствие для переданного ему аргумента

В методе showIntegerIncrementDemo мы создаём переменную increment и присваиваем ей лямбда-выражение, которое будет брать входной аргумент для унарной операции (e), прибавлять к нему единицу (e + 1) и возвращать полученный результат:

UnaryOperator<Integer> increment = e -> e + 1;

Далее мы создаём список numbers из трёх целых чисел:

List<Integer> numbers = Arrays.asList(2, 3, -5);

Следующей строкой мы применяем наш унарный оператор для инкремента к числу 3:

System.out.println(increment.apply(3));

Далее показано, как можно использовать унарный оператор при работе со стримами:

System.out.println(numbers.stream().map(increment).collect(Collectors.toList()));
System.out.println(numbers.stream().map(e -> e + 1).collect(Collectors.toList()));

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

В случае метода showGreeterDemo мы создаём простой унарный оператор, который добавляет приветствие к переданному ему строковому аргументу (мы предполагаем здесь, что это всегда будет чьё-то имя):

UnaryOperator<String> greeter = e -> "Привет, " + e + "!";

Дальше мы создаём список из имён и "приветствуем" каждого человека из списка, указывая наш унарный оператор в методе Stream#map:

List<String> people = Arrays.asList("Александр", "Иван", "Пётр", "Михаил");
System.out.println(people.stream().map(greeter).collect(Collectors.toList()));

Запустим наш класс UnaryOperatorExample и посмотрим, что будет выведено на консоль:

========================================================================================================================
>> Запуск примера для статьи "Функциональный интерфейс UnaryOperator в Java"
>> Ссылка на статью: https://allineed.ru/development/java-development/84-java-unaryoperator
========================================================================================================================
4
[3, 4, -4]
[3, 4, -4]
[Привет, Александр!, Привет, Иван!, Привет, Пётр!, Привет, Михаил!]

Мы видим, что число 3 было инкрементировано и на экран вывелся результат: 4

Далее мы видим две строки, где входной массив чисел numbers также был инкрементирован, и каждое число было увеличено на единицу.

Наконец, в конце вывода консоли отображён список, где мы приветствуем каждого человека из списка people.

Итак, мы кратко познакомились с тем, как работает функциональный интерфейс UnaryOperator<T> в Java, а также посмотрели на варианты его применения в стримах Java.

В завершение статьи отмечу, что его также можно использовать и с любыми другими доступными типами Java (не только String и Integer, как в нашем примере), включая ваши собственные классы и типы, которые вы зададите в вашей программе.

Ссылку на наш Git-репозиторий и пример кода из данной статьи, а также инструкцию по запуску примеров вы найдете внизу.

Спасибо за внимание и удачи!

Яндекс.Метрика