Java. Передача лямбда-выражения в метод в качестве параметра. Примеры

Передача лямбда-выражения в метод в качестве параметра. Примеры


Содержание


Поиск на других ресурсах:




1. Передача лямбда-выражений в качестве аргументов метода. Особенности применения. Способы передачи лямбда-выражения в метод

Лямбда-выражение может быть передано в метод в качестве аргумента. Объявление такого метода должно содержать ссылку на соответствующий функциональный интерфейс. Эта ссылка получается параметром метода, который обрабатывает лямбда-выражение.

Существует два способа передачи лямбда-выражения в метод:

  • непосредственная передача лямбда-выражения. Этот способ хорошо подходит для лямбда-выражений с малым количеством операторов;
  • передача ссылки на функциональный интерфейс, который связан с лямбда-выражением. В этом случае предварительно объявляется ссылка на интерфейс. Затем этой ссылке присваивается код лямбда-выражения. Этот способ уместен, когда лямбда-выражение становится слишком длинным для встраивания в вызов метода.

 

2. Пример, демонстрирующий способы передачи лямбда-выражения в метод

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

Способ 1. Сначала объявляется функциональный интерфейс IAverage, содержащий метод, который получает три параметра и возвращает результат типа double

// Интерфейс, объявляющий метод вычисления
// среднего арифметического из 3-х чисел.
interface IAverage {
  double Avg(double a, double b, double c);
}

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

// Класс, содержащий реализацию метода,
// который получает параметром ссылку на интерфейс IAverage
class SomeClass {

  // Метод, который выводит на экран среднее арифметическое трех чисел.
  // Метод получает ссылку на функциональный интерфейс IAverage.
  // Программный код вычисления среднего арифметического формируется
  // в лямбда-выражении, которое передается аргументом в этот метод.
  public void PrintAverage(IAverage ref) {
    System.out.println("ref = " + ref.Avg(3, 7, 8));
  }
}

После этого, в некотором клиентском методе (например, методе main()) нужно передать соответствующее лямбда выражение в метод PrintAverage() примерно следующим образом:

...

public static void main(String[] args) {
  // Клиентский код - демонстрирует передачу в метод лямбда-выражения
  // 1. Создать экземпляр класса SomeClass
  SomeClass obj = new SomeClass();

  // 2. Вызвать метод PrintAverage() и передать ему лямбда-выражение
  obj.PrintAverage((a,b,c) -> (a+b+c)/3.0);
}

...

 

Способ 2. При этом способе предварительно формируется ссылка на интерфейс. Затем этой ссылке присваивается лямбда-выражение. После этого эта ссылка передается в метод PrintAverage(). Такой подход полезен, когда код лямбда-выражения слишком большой и усложняет восприятие вызова метода. Далее приведен измененный код предыдущего примера.

...

public static void main(String[] args) {
  // Клиентский код - демонстрирует передачу в метод лямбда-выражения
  // 1. Объявить ссылку на интерфейс IAverage
  IAverage ref;

  // 2. Присвоить ссылке на интерфейс IAverage
  // лямбда-выражение, вычисляющее среднее арифметическое 3-х значений
  ref = (a, b, c) -> (a+b+c)/3.0;

  // 3. Создать экземпляр класса SomeClass
  SomeClass obj = new SomeClass();

  // 4. Вызвать метод PrintAverage()
  obj.PrintAverage(ref);
}

 

3. Примеры решения задач, в которых лямбда-выражение передается в качестве аргумента метода
3.1. Максимальное значение в массиве чисел. Шаблонный функциональный интерфейс. Передача лямбда-выражения в статический метод

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

Решение. В задаче объявляется обобщенный (шаблонный) функциональный интерфейс IArray. В интерфейсе определен один метод, который получает массив чисел типа T и возвращает значение типа T.
Класс Lambda является основным классом в программе, который содержит функцию main(). В функции main() формируются:

  • лямбда-выражение, вычисляющее максимальное значение в массиве A, которое является входным параметром. Следует обратить внимание, что массив A указывается параметром лямбда-выражения без скобок [ ];
  • массив целых чисел, который передается в статический метод Solution().

С целью демонстрации, в классе Lambda реализовано статический шаблонный метод Solution(), который получает два параметра:

  • массив обобщенного типа T, в котором нужно найти максимальный элемент;
  • лямбда-выражение, которое передается в метод как ссылка ref на функциональный интерфейс IArray.

Текст решения задачи следующий

// Функциональный интерфейс IArray
interface IArray<T extends Number> {
  // Метод поиска максимума в массиве чисел
  T Max(T[] array);
}

// Класс, содержащий методы, реализующие лямбда-выражение и
// тестирующие работу программы.
public class Lambda {

  // Статический шаблонный метод, получающий параметром лямбда-выражение.
  // Метод оперирует типом T.
  // Тип T ограничен типом Number - это значит, что тип T может
  // быть только числовым типом (double, float, int, ...).
  // Параметры метода:
  // - массив чисел типа T;
  // - ссылка на интерфейс IArray<T>, в котором реализовано лямбда-выражение.
  public static <T extends Number> void Solution(T[] array, IArray<T> ref) {
    // Вывести максимальное значение в массиве
    T max = ref.Max(array);
    System.out.println("max = " + max);
  }

  public static void main(String[] args) {
    // Сформировать лямбда-выражение, вычисляющее максимальное значение
    // в массиве целых чисел
    IArray<Integer> refInt = (A) -> {
      Integer max = A[0];
      for (int i=0; i<A.length; i++)
        if (max<A[i]) max = A[i];
          return max;
    };

    // Создать массив целых чисел
    Integer[] A = { 7, 3, 2, 8, 8, 4 };

    // Передать лямбда-выражение в метод Solution()
    Lambda.Solution(A, refInt); // max = 8
  }
}

Результат работы программы

max = 8

 

3.2. Сортировка массива строк методом вставки. Алгоритм сортировки передается лямбда-выражением

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

// Функциональный интерфейс, предназначенный
// для сортировки массива строк
interface ISortStrings {
  void Sort(String[] array);
}

// Класс, содержащий метод, в который передается лямбда-выражение
class SortMethods {
  // Метод, который сортирует и выводит отсортированные строки.
  // В метод передается лямбда-выражение в виде ссылки ref.
  void SortStrings(String[] AS, ISortStrings ref) {
    // Отсортировать массив AS
    ref.Sort(AS);

    // Вывести отсортированный массив
    for (String s : AS)
      System.out.println(s);
  }
}

public class Lambda2 {

  public static void main(String[] args) {
    // 1. Объявить ссылку на ISortStrings
    ISortStrings ref;

    // 2. Определить лямбда-выражение для алгоритма сортировки вставками.
    // Сортировка происходит по возрастанию: A...Z
    ref = (s) -> {
      String tmp;
      for (int i=0; i<s.length-1; i++)
        for (int j=i; j>=0; j--)
          if (s[j].compareTo(s[j+1])>0) {
            tmp = s[j];
            s[j] = s[j+1];
            s[j+1] = tmp;
          }
    };

    // 3. Сформировать тестирующий массив строк
    String[] AS = {
      "afd", "jkl", "jprst", "mno", "axf", "aaa", "bcd", "ghi"
    };

    // 4. Вызвать метод сортировки SortMethods() и передать ему лямбда-выражение
    SortMethods obj = new SortMethods(); // создать экземпляр класса
    obj.SortStrings(AS, ref);
  }
}

Результат выполнения программы

aaa
afd
axf
bcd
ghi
jkl
jprst
mno

 

3.3. Вычисление количества вхождений элемента в массиве. Обобщенный функциональный интерфейс

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

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

Продемонстрировать работу метода в функции main().

// Обобщенный функциональный интерфейс.
interface IFindItem<T> {
  // Метод для определения количества вхождений элемента в массиву
  int NOccurences(T item, T[] array);
}

// Класс, содержащий метод, в который передается лямбда-выражение
class FindItems<T> {
  // Метод, который получает:
  // - item - искомый элемент типа T;
  // - array - массив элементов типа T;
  // - ref - ссылка на лямбда-выражение.
  int Find(T item, T[] array, IFindItem<T> ref) {
    // Определить количество вхождений item в array
    int count = ref.NOccurences(item, array);
    return count;
  }
}

// Класс, содержащий методы, реализующие лямбда-выражение
// и тестирующие работу программы.
public class Lambda {

  public static void main(String[] args) {
    // Продемонстрировать поиск для строк
    // 1. Объявить ссылку на NOccurences
    IFindItem<String> ref;

    // 2. Сформировать лямбда-выражение для типа String
    ref = (item, array) -> {
      int n = 0; // количество вхождений
      for (int i=0; i<array.length; i++)
        if (item==array[i])
          n++;
      return n;
    };

    // 3. Объявить тестируемый масив
    String[] AS = { "abc", "def", "abc", "ghi", "fjk", "def", "def" };

    // 4. Вызвать метод Find() и вывести количество вхождений "def" в AS
    FindItems<String> obj = new FindItems<String>();
    int count = obj.Find("def", AS, ref); // count = 3
    System.out.println("count = " + count);
  }
}

Результат выполнения программы

count = 3

 


Связанные темы