lambda表达式
Lambda 是一个匿名函数,可以把 Lambda表达式 理解为是一段可以传递的代码 (将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升
java为支持函数式编程,引入lambda表达式:lambda表达式是实现仅有一个抽象方法的接口的简化实现.
lambda表达式可完全替代匿名内部类(只有一个抽象方法的情况下),并且没有匿名内部类中new Xxx(){}
这样繁琐的表达结构。
在接口中只定义一个抽象方法(可以有普通方法和静态方法)为后来的lambda表达式做准备的情况下,可以使用注解@FunctionalInterface,这样IDE在编译阶段就会自动检测接口中是否只有一个抽象方法,及时报错.
lambda表达式格式
Lambda 表达式的基础语法 : JDK1.8 中引入了一个新的操作符 “->” 该操作符称为箭头操作符或 Lambda 操作符,箭头操作符将 Lambda 表达式拆分成两部分 :
左侧 : Lambda 表达式的参数列表
右侧 : Lambda 表达式中所需执行的功能, 即 Lambda 体
接口实现类类名 对象名=([接口中抽象方法的参数列表]) ->{
//抽象方法实现语句;
};
在lambda表达式所在的作用域下,参数列表中的参数名不能和作用域中的其他变量名冲突
lambda表达式中的参数个数与接口中抽象方法的参数个数对应
1.如果抽象方法的实现只有一条命令,大括号可以省略
()->单条实现语句;
interface IUtil{
void print();
}
public class TestUtil {
IUtil iutil = new IUtil() {
@Override
public void print() {
System.out.println("匿名内部类实现接口的抽象方法");
}
};
public static void main(String[] args) {
//lambda表达式中,方法的实现只有一行代码,大括号可以省略
IUtil iutil1 = ()-> System.out.println("lambda表达式实现接口抽象方法");
iutil1.print();
TestUtil testUtil =new TestUtil();
testUtil.iutil.print();
}
}
2.如果抽象方法有返回值,且lambda表达式中只有返回语句,此时大括号和return关键字都可省略
()->返回值;
interface Funinter2{
String print();
}
public class TestLambda2 {
public static void main(String[] args) {
//括号中的参数与抽象方法的参数对应
// (参数名可以重起,遵循不能与作用域内变量名重复的原则)
//只有返回值可简写
Funinter2 fun2=()->"hello";
System.out.println(fun2.print(78));
}
}
3.多条语句(返回值+实现语句/多条实现语句)的情况下,大括号不能省略
()->{
实现语句1;
实现语句2;
...
return xxx;
}
interface Funinter3{
String print(char ch);
}
public class TestLambda3 {
public static void main(String[] args) {
Funinter2 fun2=(ch)->{
char temp='C'+32;
return temp+""+ch;
};
System.out.println(fun2.print('b'));
}
}
4.只有一个参数,小括号可以省略不写
参数1->{
}
interface Funinter2{
String print(int num);
}
public class TestLambda2 {
public static void main(String[] args) {
//括号中的参数与抽象方法的参数对应
// (参数名可以重起,遵循不能与作用域内变量名重复的原则)
//只有返回值可简写,只有一个参数可省略小括号
Funinter2 fun2=num->"hello";
System.out.println(fun2.print(78));
}
}
方法引用:在JDK1.8中,加入方法引用,方法引用需与lambda表达式配合使用,方法引用的实质就是给方法起了个别名.
1.引用静态方法
类名称::静态方法名称
public interface IUtil1 {
String convert(Integer in);
public static void main(String[] args) {
//1.引用静态方法
IUtil1 iUtil1 =String::valueOf;
System.out.println(iUtil1.convert(34));//34
String s=iUtil1.convert(34);
System.out.println(s.charAt(1));//4
}
}
2.引用特定对象的实例方法
实例化对象::普通方法
@FunctionalInterface
public interface IUtil2 {
int convert(String str);
public static void main(String[] args) {
String str="ni hao ";
//调用"ni hao "对象的实例方法indexOf(同样是入参为String,返回值为int)
IUtil2 iUtil2=str::indexOf;
System.out.println(iUtil2.convert("n"));
}
}
3.引用类中普通方法
类名称::普通方法名
@FunctionalInterface
public interface IUtil3 {
//抽象方法入参为Person类,返回类型为String
String getInfo(Person person);
public static void main(String[] args) {
//引用Person的普通方法getPersonInfo
IUtil3 iUtil33=Person::getPersonInfo;
System.out.println(iUtil33.getInfo(new Person(23,"nancy")));;
}
}
class Person{
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public String getPersonInfo(){
return "姓名"+this.name+"年龄"+this.age;
}
}
4.引用构造方法
@FunctionalInterface
public interface IUtil4 {
Person4 print(int a, String b);
public static void main(String[] args) {
IUtil4 iUtil4 =Person4::new;
}
}
class Person4{
private int age;
private String name;
public Person4(int age, String name) {
this.age = age;
this.name = name;
}
public String getPersonInfo(){
return "姓名"+this.name+"年龄"+this.age;
}
}
Lamdba的核心在于:函数式接口。
而函数式接口的核心:只有一个方法。
java.util.function 实际上函数式编程分为以下四种接口:
- 功能型函数式接口:public interface Function<T, R> R apply(T t);
- 供给型函数式接口: public interface Supplier T get();
- 消费型函数式接口:public interface Consumer void accept(T t);
- 断言型接口:public interface Predicate boolean test(T t);