Лямбда-вирази для узагальнених функціональних інтерфейсів. Приклади
Зміст
- 1. Особливості використання узагальнень (шаблонів) в функціональних інтерфейсах
- 2. Розв’язки задач на побудову лямбда-виразів, що реалізують узагальнені функціональні інтерфейси. Приклади
- Зв’язані теми
Пошук на інших ресурсах:
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
⇑
Зв’язані теми
- Лямбда-вирази. Основні поняття. Функціональний інтерфейс. Приклади
- Передача лямбда-виразу в метод в якості параметру. Приклади
- Генерування виключень у лямбда-виразах. Приклади
- Доступ до елементів класу з лямбда-виразу. Захоплення змінних у лямбда-виразах. Приклади
⇑