Java. Лямбда-выражения для обобщенных функциональных интерфейсов. Примеры




Лямбда-выражения для обобщенных функциональных интерфейсов. Примеры


Содержание


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

1. Особенности использования обобщений (шаблонов) в функциональных интерфейсах

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

Например. Пусть задан обобщенный функциональный интерфейс IValue

// Обобщенный (шаблонный) функциональный интерфейс.
// Этот интерфейс оперирует обобщенным типом T.
interface IValue<T> {
  T GetValue();
}

Интерфейс IValue<T> оперирует обобщенным типом T. В интерфейсе объявляется абстрактный метод GetValue(), который возвращает значение типа T. Следовательно, этот функциональный интерфейс совместим с любым лямбда-выражением, принимающим один параметр и возвращающим значение этого же типа.

При объявлении ссылки на функциональный интерфейс IValue<T> в аргументе типа нужно указать целевой тип лямбда-выражения:

// Объявить ссылку на функциональный интерфейс IValue,
// который будет оперировать типом Float
IValue<Float> refIValue;

После этого можно сформировать лямбда-выражение и вызвать метод GetValue()

// Установить лямбда-выражение с привязкой к типу Float
refIValue = () -> 3.1415f; // вернуть значение типа float

// Вызвать метод GetValue(), который возвращает 3.1415f
float v = refIValue.GetValue(); // v = 3.1415

Если при формировании лямбда-выражения попытаться вернуть значение другого (несовместимого) типа

refIValue = () -> "Hello world!"; // здесь тип String а не Float

то компилятор выдаст ошибку типа

Type mismatch: cannot convert from String to Float

Чтобы лямбда-выражение возвращало тип String, нужно объявить новую ссылку на интерфейс IValue с аргументом типа String (IValue <String>).

 

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

В примере демонстрируется:

  • объявление обобщенного (шаблонного) функционального интерфейса IValue<T>, оперирующего типом T;
  • создание лямбда-выражения и его использование для числового типа Float. Лямбда-выражение реализует обобщенный функциональный интерфейс IValue<T>.

 

// Обобщенный (шаблонный) функциональный интерфейс.
// Этот интерфейс оперирует обобщенным типом T.
interface IValue<T> {
  T GetValue();
}

public class TrainLambda02 {

  public static void main(String[] args) {

    // Объявить ссылку на функциональный интерфейс IValue,
    // который будет оперировать типом Float
    IValue<Float> refIValue;

    // Установить лямбда-выражение с привязкой к типу Float
    refIValue = () -> 3.1415f; // вернуть значение типа float

    // Вызвать метод GetValue(), который вернет 3.1415f
    float v = refIValue.GetValue(); // v = 3.1415
    System.out.println("v = " + v);
  }
}

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

v = 3.1415

 

2.2. Лямбда-выражение, реализующее поэлементное суммирование массивов чисел

Условие задачи. Разработать программу, в которой осуществляется поэлементное суммирование массивов из 10 чисел. Тип чисел может быть любым числовым (int, double, float, …). Суммирование массивов реализовать с помощью лямбда-выражения.

Решение. Чтобы суммировать два массива чисел, нужно реализовать функциональный интерфейс ISumArrays, который содержит один метод SumArrays(). Этот метод должен получать два параметра — массивы чисел. Метод должен возвращать результат — массив чисел, который является суммой двух массивов-параметров.

В условии задачи сказано, что тип чисел может быть любым числовым (int, double, float, …). Это значит, что нужно разработать обобщенный (шаблонный) интерфейс ISumArrays для некоторого типа T. Поскольку тип T ограничивается числовыми типами, то его нужно ограничить типом Number.

В функции main() нужно протестировать работу созданного функционального интерфейса.

Ниже приведен текст программы, решающей данную задачу.

// Шаблонный функциональный интерфейс ISumArrays
interface ISumArrays<T extends Number> {
  T[] SumArrays(T[] A, T[] B);
}

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

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

    // 2. Создать два массива типа double
    Double[] A1 = { 2.5, 1.4, 0.9, 1.1, 2.7, 2.9, 1.3, 2.0, 5.5, 1.2 };
    Double[] A2 = { 1.5, 1.0, 0.6, 1.7, 0.7, 0.2, 0.3, 0.2, 1.1, 3.3 };

    // 3. Сформировать лямбда-выражение для типа Double
    ref = (A, B) -> {
      Double[] C = new Double[A.length]; // числовой тип в массивах
      for (int i=0; i<A.length; i++)
      {
        // суммировать два числа как double
        C[i] = A[i].doubleValue() + B[i].doubleValue();
      }
      return C;
    };

    // 4. Вызвать метод функционального интерфейса
    Double[] A3 = (Double[])ref.SumArrays(A1, A2);

    // 5. Вывести результат
    System.out.print("A3: ");
    for (Double t : A3)
      System.out.print(" " + t);
    System.out.println();
  }
}

В вышеприведенном коде следует обратить внимание на то, как передаются массивы чисел в лямбда-выражение

...

ref = (A, B) -> {
  Double[] C = new Double[A.length]; // числовой тип в массивах
  for (int i=0; i<A.length; i++)
  {
    // суммировать два числа как double
    C[i] = A[i].doubleValue() + B[i].doubleValue();
  }
  return C;
};

...

Поскольку тип параметра лямбда-выражения определяется из целевого контекста, то массивы в лямбда выражение передаются как A и B. Параметр A ассоциируется с A[]. Параметр B ассоциируется с B[].

 

2.3. Вычисления количества вхождений заданного элемента в массиве

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

Решение. Текст программы, решающий данную задачу приведен ниже

 

// Шаблонный функциональный интерфейс IFindItem
interface IFindItem<T> {
  // метод, вычисляющий количество вхождений
  // заданного элемента в массиве чисел
  int Search(T item, T[] items);
}

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

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

    // 2. Определить лямбда-выражение
    ref = (item, items) -> {
      int count=0;
      for (int i=0; i<items.length; i++)
        if (item==items[i])
          count++;
      return count;
    };

    // 3. Создать массив строк
    String[] AS = { "abc", "abd", "def", "acf", "abc", "afx" };

    // 4. Протестировать лямбда-выражение
    int count = ref.Search("abc", AS);
    System.out.println("count = " + count); // count = 2
  }
}

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

count = 2

 


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