عبارات لامبدا در عمل

چند مثال ساده که مفاهیم اساسی عبارات لامبدا را عملی می کند:
مثال 1 – مقایسه اجرای بدون و با لامبدا
بدون استفاده از لامبدا:
interface MyValueSemLambda1 {
double getValue(); // Método abstrato
}
class MyValueImpl implements MyValueSemLambda1{
private double value;
// Construtor para inicializar o atributo value
public MyValueImpl(double value) {
this.value = value;
}
// Implementação do método getValue
@Override
public double getValue() {
return this.value;
}
}
public class MyValueSemLambda {
public static void main(String[] args) {
MyValueSemLambda1 myVal = new MyValueImpl(98.6); // Atribuindo valor ao atributo
System.out.println("Value: " + myVal.getValue()); // Imprime 98.6
}
}
استفاده از لامبدا:
interface MyValueCompara {
double getValue();
}
public class MyValueComparacao {
public static void main(String[] args) {
// Expressão lambda sem atributo, mas retornando um valor
MyValueCompara myVal = () -> 98.6;
System.out.println("Value: " + myVal.getValue()); // Imprime 98.6
}
}
مثال 2 – LambdaDemo
// Uma interface funcional.
interface MyValue {
double getValue();
}
// Outra interface funcional.
interface MyParamValue {
double getValue(double v);
}
class LambdaDemo {
public static void main(String args[])
{
MyValue myVal; // declara uma referência de interface
// Aqui, a expressão lambda é simplesmente uma expressão de constante.
// Quando ela é atribuída a myVal, é construída a instância
// de uma classe em que a expressão lambda implementa o
// método getValue() de MyValue.
myVal = () -> 98.6; Uma expressão lambda simples
// Chama getValue(), que é fornecido pela
// expressão lambda atribuída anteriormente.
System.out.println("A constant value: " + myVal.getValue());
// Agora, cria uma expressão lambda parametrizada e a atribui
// a uma referência de MyParamValue. Essa expressão lambda retorna
// o recíproco de seu argumento.
MyParamValue myPval = (n) -> 1.0 / n; Uma expressão lambda
que tem um parâmetro
// Chama getValue() por intermédio da referência de myPval.
System.out.println("Reciprocal of 4 is " + myPval.getValue(4.0));
System.out.println("Reciprocal of 8 is " + myPval.getValue(8.0));
// Uma expressão lambda deve ser compatível com o método definido
// pela interface funcional. Logo, essas instruções não funcionarão:
// myVal = () -> "three"; // Erro! String não é compatível com double!
// myPval = () -> Math.random(); // Erro! O parâmetro é necessário!
}
}
خروج:
مقدار ثابت: 98.6
متقابل 4 برابر 0.25 است
متقابل 8 0.125 است
- عبارت لامبدا باید با روش انتزاعی که پیاده سازی می کند سازگار باشد.
نمونه ای از ناسازگاری ها:
-
اگر نوع بازگشت مورد انتظار دو برابر باشد، نمی توان از مقدار رشته استفاده کرد.
-
روشی که به یک پارامتر نیاز دارد بدون ارائه آن قابل استفاده نیست.
-
یک رابط کاربردی را می توان با هر عبارت لامبدا سازگار استفاده کرد.
مثال 3 – NumericTest
تست تقسیم پذیری: بررسی می کند که آیا عدد اول بر عدد دوم بخش پذیر است یا خیر.
مقایسه اندازه: تعیین می کند که آیا عدد اول کمتر از عدد دوم است یا خیر.
مقایسه مقادیر مطلق: اگر مقادیر مطلق دو عدد مساوی باشند، true را برمیگرداند.
- Em
main( )
، سه تست مختلف با استفاده از عبارات لامبدا ایجاد می شود.
// Interface funcional que usa dois parâmetros int e
// retorna um resultado boolean.
interface NumericTest {
boolean test(int n, int m);
}
class LambdaDemo2 {
public static void main(String args[])
{
// Esta expressão lambda determina se um número
// é fator de outro.
NumericTest isFactor = (n, d) -> (n % d) == 0;
if(isFactor.test(10, 2))
System.out.println("2 is a factor of 10");
if(!isFactor.test(10, 3))
System.out.println("3 is not a factor of 10");
System.out.println();
// Esta expressão lambda retorna true se o
// primeiro argumento for menor do que o segundo.
NumericTest lessThan = (n, m) -> (n < m);
if(lessThan.test(2, 10))
System.out.println("2 is less than 10");
if(!lessThan.test(10, 2))
System.out.println("10 is not less than 2");
System.out.println();
// Esta expressão lambda retorna true se os
// valores absolutos dos argumentos forem iguais.
NumericTest absEqual = (n, m) -> (n < 0 ? -n : n) == (m < 0 ? -m : m);
if(absEqual.test(4, -4))
System.out.println("Absolute values of 4 and -4 are equal.");
if(!lessThan.test(4, -5))
System.out.println("Absolute values of 4 and -5 are not equal.");
System.out.println();
}
}
خروج:
2 ضریب 10 است
3 ضریب 10 نیست
2 کمتر از 10 است
10 کمتر از 2 نیست
مقادیر مطلق 4 و -4 برابر هستند.
مقادیر مطلق 4 و -5 برابر نیستند.
-
عبارات لامبدا سازگار را می توان با همان رابط کاربردی استفاده کرد.
-
از همان متغیر مرجع می توان برای عبارات مختلف لامبدا استفاده مجدد کرد.
-
استفاده مجدد از متغیرها خواندن را آسانتر می کند و منابع کد را ذخیره می کند.
-
در مثال، یک رابط برای پیاده سازی های مختلف استفاده می شود:
NumericTest myTest;
myTest = (n, d) -> (n % d) == 0; //implementação 1
if(myTest.test(10, 2))
System.out.println("2 is a factor of 10");
// ...
myTest = (n, m) -> (n < m); //implementação 2
if(myTest.test(2, 10))
System.out.println("2 is less than 10");
//...
myTest = (n, m) -> (n < 0 ? -n : n) == (m < 0 ? -m : m); //implementação 3
if(myTest.test(4, -4))
System.out.println("Absolute values of 4 and -4 are equal.");
// ...
وضوح با متغیرهای مرجع
استفاده از متغیرهای مرجع مختلف (به عنوان مثال isFactor، lessThan، absEqual) کمک می کند تا به وضوح مشخص شود که هر متغیر کدام عبارت لامبدا را نشان می دهد.
تعیین چند پارامتر
چندین پارامتر در عبارات لامبدا با کاما در یک لیست پرانتز در سمت چپ عملگر لامبدا از هم جدا می شوند.
مثال: (n, d) -> (n % d) == 0
.
استفاده از انواع مختلف در عبارات لامبدا
در روشهای انتزاعی رابطهای تابعی محدودیتی در نوع پارامترها یا بازگشتها وجود ندارد.
انواع داده های غیر ابتدایی مانند String را می توان در عبارات لامبدا استفاده کرد.
نمونه تست با رشته ها
یک رابط کاربردی را می توان برای آزمایش شرایط خاص مرتبط با رشته استفاده کرد، مانند بررسی اینکه آیا یک رشته در رشته دیگری وجود دارد یا خیر.
// Uma interface funcional que testa dois strings.
interface StringTest {
boolean test(String aStr, String bStr);
}
class LambdaDemo3 {
public static void main(String args[])
{
// Esta expressão lambda determina se um string faz
// parte de outro.
StringTest isIn = (a, b) -> a.indexOf(b) != -1;
String str = "This is a test";
System.out.println("Testing string: " + str);
if(isIn.test(str, "is a"))
System.out.println("'is a' found.");
else
System.out.println("'is a' not found.");
if(isIn.test(str, "xyz"))
System.out.println("'xyz' Found");
else
System.out.println("'xyz' not found");
}
}
خروج:
رشته تست: این یک تست است
'است' یافت شد.
“xyz” پیدا نشد
رابط کاربردی StringTest
یک آزمایش روش انتزاعی (String aStr، String bStr) را تعریف می کند که یک مقدار بولی را برمی گرداند.
پیاده سازی با بیان لامبدا
عبارت لامبدا (a, b) -> a.indexOf(b) != -1 بررسی می کند که آیا یک رشته (b) در (a) دیگری وجود دارد یا خیر.
استنتاج را در پارامترها تایپ کنید
پارامترهای a و b از نوع String استنباط می شود که امکان استفاده از روش های کلاس String مانند indexOf را فراهم می کند.
این برنامه رشته “This is a test” را آزمایش می کند تا ببیند آیا زیر رشته های “is a” و “xyz” است یا خیر، نتایج را مطابق با آن چاپ می کند.