Lambda表达式可以看做是一个匿名类。将一个Lambda表达式做为参数传递给方法,行为参数化,就实现了函数式编程。
在没有Lambda之前,要实现函数式编程就需要使用匿名类,如果用Lambda会使得代码更加简洁、清晰。
举个例子:
如果要实现传递方法的方式实现加法和减法,可以使用下面匿名类的写法:
public class Demo0 {
//两个参数的运算
interface MathOperation {
double operation(double a, double b);
}
public static void main(String[] args) {
//加法
MathOperation add=new MathOperation() {
@Override
public double operation(double a, double b) {
return a+b;
}
};
//减法
MathOperation sub=new MathOperation() {
@Override
public double operation(double a, double b) {
return a-+b;
}
};
System.out.println("20+10:" + add.operation(20, 10));
System.out.println("20-10:" + sub.operation(20, 10));
}
}
如果用Lambda表达式实现,可以写作下面的方式:
public class Demo1 {
//两个参数的运算
interface MathOperation {
double operation(double a, double b);
}
public static void main(String[] args) {
//加法
MathOperation add = (double a, double b) -> a + b;
//减法
MathOperation sub = (a, b) -> a - b;
System.out.println("20+10:" + add.operation(20, 10));
System.out.println("20-10:" + sub.operation(20, 10));
}
}
这里将内部类的变为了Lambda表达式,简化了代码。
Lambda的表达式结构如下:
(variable)->action
举例
public class Demo1 {
//没有参数的运算
interface NoParamOperation {
double operation();
}
//一个参数的运算
interface SingleParamOperation {
int operation(int a);
}
//两个参数的运算
interface MathOperation {
double operation(double a, double b);
}
public static void main(String[] args) {
//======几种Lambda表达式的写法=============
//得到PI值(没有参数,直接返回)
NoParamOperation pi = () -> Math.PI;
//得到自然常数 (没有参数,直接返回,如果有花括号,要写上显式的加上return)
NoParamOperation e = () -> {
return Math.E;
};
//求平方(如果参数是一个,可以省略小括号)
SingleParamOperation square = a -> a * a;
//求立方(可以指定参数的类型,如果没有编译器会自动推算)
SingleParamOperation cubic = (int a) -> a * a * a;
//加法(如果多个参数,就必须添加上小括号)
MathOperation add = (double a, double b) -> a + b;
//减法(多个参数,也可以不指定参数的数据类型)
MathOperation sub = (a, b) -> a - b;
//乘法(一行代码,函数体上也可以写上花括号)
MathOperation mult = (double a, double b) -> {
return a * b;
};
//除法(如果函数体有多行,就必须有花括号)
MathOperation div = (a, b) -> {
if (b != 0) {
return a / b;
} else {
return 0;
}
};
System.out.println("PI的值" + pi.operation());
System.out.println("自然常数E的值:" + e.operation());
System.out.println("10的平方:" + square.operation(10));
System.out.println("10的立方:" + cubic.operation(10));
System.out.println("20+10:" + add.operation(20, 10));
System.out.println("20-10:" + sub.operation(20, 10));
System.out.println("20*10:" + mult.operation(20, 10));
System.out.println("20/10:" + div.operation(20, 10));
}
}
方法引用是Lambda表达式的一种简写,格式为:
ObjectRef::methodName
有三种方法引用类型:静态方法引用、实例方法引用、构造方法引用
package javademo.lambda.MathOperationDemo;
public class Demo2Util {
static double formatPrint(String format, double a, double b) {
double r = a + b;
System.out.format(format, r);
return r;
}
}
package javademo.lambda.MathOperationDemo;
public class Demo2 {
//两个参数的运算
interface MathOperation {
double operation(String format, double a, double b);
}
public static void main(String[] args) {
//内部类方式,方法中只调用了一个静态方法formatPrint
MathOperation add = new MathOperation() {
@Override
public double operation(String format, double a, double b) {
return Demo2Util.formatPrint(format, a, b);
}
};
//Lambda方式,调用了静态方法
MathOperation add1 = (f, a, b) -> Demo2Util.formatPrint(f, a, b);
//静态方法引用方式,代码更紧凑简洁
MathOperation add2 = Demo2Util::formatPrint;
add.operation("内部类方式:%f", 20, 10);
add1.operation("Lambda方式:%f", 20, 10);
add2.operation("方法引用方式:%f", 20, 10);
}
}
如果方法中是调用某一个对象的方法,可以简写为方法引用的方式。
package javademo.lambda.MathOperationDemo;
public class Demo3Helper {
//这里将方法放到一个类中
public double formatPrint(String format, double a, double b) {
double r = a + b;
System.out.format(format, r);
return r;
}
}
package javademo.lambda.MathOperationDemo;
public class Demo3 {
//两个参数的运算
interface MathOperation {
double operation(String format, double a, double b);
}
public static void main(String[] args) {
Demo3Helper helper = new Demo3Helper();
//匿名类的方式,方法中调用了helper对象的一个方法。
MathOperation add1 = new MathOperation() {
@Override
public double operation(String format, double a, double b) {
return helper.formatPrint(format, a, b);
}
};
//Lambda方式,方法体内只是调用一个对象的方法。
MathOperation add2 =(f,a,b)-> helper.formatPrint(f,a,b);
//这个时候,就可以简写为方法引用
MathOperation add3 = helper::formatPrint;
add1.operation("匿名类的方式:%f\n", 20, 10);
add2.operation("Lambda方式:%f\n", 20, 10);
add3.operation("方法引用方式:%f\n", 20, 10);
}
}
当接口的方法里操作是实例化一个对象时,比如下面例子里,只是new 一个对象,对应的Lambda表达式可以简化为构造方法引用方式。
举例:
package javademo.lambda.MathOperationDemo;
public class Demo5 {
//计算器类
static class Calculator {
//计算器类,一个参数的构造函数
public Calculator(String name) {
this.name = name;
}
//计算器类,两个参数的构造函数
public Calculator(Integer id,String name)
{
this.id=id;
this.name=name;
}
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//计算器接口,有一个创建计算器的方法
interface ICalculator {
Calculator create(String name);
}
//计算器接口,有两参数个创建计算器的方法
interface ICalculator2 {
Calculator create(Integer id,String name);
}
public static void main(String[] args) {
//第1种方式:内部类方式创建电脑对象和中国算盘对象
ICalculator pc1 = new ICalculator() {
@Override
public Calculator create(String name) {
return new Calculator(name);
}
};
ICalculator2 pc11=new ICalculator2() {
@Override
public Calculator create(Integer id, String name) {
return new Calculator(id,name);
}
};
//第2种方式:用Lambda表达式创建
ICalculator pc2 = (name) -> new Calculator(name);
ICalculator2 pc22=(id,name)->new Calculator(id,name);
//第3种方式:用方法引用方式进一步简化Lambda表达式。
ICalculator pc3 = Calculator::new;
ICalculator2 pc33=Calculator::new;
Calculator c1 = pc1.create("电脑1");
Calculator c11 = pc11.create(11,"电脑11");
Calculator c2 = pc2.create("电脑2");
Calculator c22=pc22.create(22,"电脑22");
Calculator c3 = pc3.create("电脑3");
Calculator c33=pc33.create(33,"电脑33");
}
}