Lambda表达式简介:
一、什么是Lambda表达式?
- Lambda表达式也被称为箭头函数、匿名函数、闭包
- Lambda表达式提现的是轻量级函数式编程思想
- ‘->’ 符号是Lambda表达式核心操作符号,符号左侧是操作参数,符号右侧是操作表达式
- Lambda表达式时JDK8的新特性
二、为什么要用Lambda表达式
- 它不是解决未知问题的新技术
- 对现有解决方案的语义化优化
- 需要根据实际需求考虑性能问题
Lambda表达式基础知识:
一、函数式接口(function interface)的特性
- 函数式接口是Java类型系统中的接口
- 函数式接口是只包含一个抽象接口方法的特殊接口
- JDK8提供的语义化检测注解:@FunctionalInterface
二、在函数式接口中允许存在的方法,并且不影响其特性。有如下3种:
- 默认(default)接口方法:给所有的实现了接口的对象,增加的通用方法,必须有具体的实现。
- 静态(static)接口方法:必须有具体的实现。
- 继承自Object类的方法,不论是具体还是抽象方法。
三、函数式接口与Lambda表达式的联系
- 函数式接口,只包含一个抽象方法;Lambda表达式,只能操作一个方法。
- Java中的Lambda表达式,核心就是一个函数式接口的实现。
四、函数式接口的实现可以有三种方式
- 创建一个接口的实现类; (最常见)
- 匿名内部类实现接口; (灵活,冗余)
- Lambda表达式实现接口。(灵活,简洁)
第1种最为常见,就不列举了,只对比2,3两种情况:
@FunctionalInterface
public interface IUserCredential {
/**
*
* @param username 用户名
* @return 验证结果
*/
String verifyUser(String username);
}
public class App
{
public static void main( String[] args )
{
//匿名内部类实现接口
IUserCredential iuc1 = new IUserCredential() {
@Override
public String verifyUser(String username) {
return username.equals("admin")?"系统管理员":"普通用户";
}
};
System.out.println(iuc1.verifyUser("admin"));
System.out.println(iuc1.verifyUser("user"));
//Lambda表达式实现接口
IUserCredential iuc2 = (String username)->{ //此处的String声明可以省略,因为Lambda表达式会自动进行类型检查
return username.equals("admin")?"系统管理员":"普通用户";
};
System.out.println(iuc2.verifyUser("admin"));
System.out.println(iuc2.verifyUser("user"));
}
}
五、Lambda表达式基本语法
- 声明:就是和Lambda表达式绑定的接口类型
- 参数:包含在一对圆括号中,和绑定的接口中的抽象方法中的参数个数及顺序一致。(参数的类型可以不用指定,jvm在运行时,会自动根据绑定的抽象方法中的参数自动推导)
- 操作符:->
- 执行代码块:包含在一对大括号中,出现在操作符号的右侧。(如果代码块中只有一行,此时大括号可以省略且return关键字也可以省略;如果有多行,或者添加了大括号,必须通过return关键字进行返回)
六、匿名内部类与Lambda表达式的区别
语法冗余:
//1.传统模式下,新线程的创建
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("CurrentThreadId......"+Thread.currentThread().getId());
}
}).start();
//2.使用Lambda表达式创建新线程
new Thread(()->{
System.out.println("CurrentThreadId......"+Thread.currentThread().getId());
}).start();
this关键字混淆:Lambda表达式中的变量操作优化了匿名内部类中的this关键字,不再单独建立对象作用域,表达式本身就是所属对象的一部分。
public class App2 {
String s1 = "全局变量";
// 1. 匿名内部类型中对于变量的访问
public void testInnerClass() {
String s2 = "局部变量";
new Thread(new Runnable() {
String s3 = "内部变量";
@Override
public void run() {
// 访问全局变量
// System.out.println(this.s1);// this关键字~表示是当前内部类型的对象
System.out.println(s1);
System.out.println(s2);// 局部变量的访问,~不能对局部变量进行数据的修改[final]
// s2 = "hello";
System.out.println(s3);
System.out.println(this.s3);
}
}).start();
}
// 2. lambda表达式变量捕获
public void testLambda() {
String s2 = "局部变量lambda";
new Thread(() -> {
String s3 = "内部变量lambda";
// 访问全局变量
System.out.println(this.s1);// this关键字,表示的就是所属方法所在类型的对象
// 访问局部变量
System.out.println(s2);
// s2 = "hello";// 不能进行数据修改,默认推导变量的修饰符:final
System.out.println(s3);
s3 = "labmda 内部变量直接修改";
System.out.println(s3);
}).start();
}
public static void main(String[] args) {
App2 app = new App2();
app.testInnerClass();
app.testLambda();
}
}
七、JDK8中常见的内置函数式接口
JDK8提供了java.util.function包,提供了常用的函数式功能接口。例如:
- java.util.function.Predicate<T>--------接收参数对象T,返回一个boolean类型结果
Predicate<String> pre = (String username)->{
return "admin".equals(username);
};
System.out.println(pre.test("admin"));
System.out.println(pre.test("admir"));
- java.util.function.Consumer<T>--------接收参数对象T,不返回结果
Consumer<String> con = (String message)->{
System.out.println("需要打印的消息:" + message);
};
con.accept("hello world");
- java.util.function.Function<T,R>--------接收参数对象T,返回结果对象R
Function<String ,Integer> fun = (String gender)->{
return "male".equals(gender)?1:0;
};
System.out.println(fun.apply("male"));
System.out.println(fun.apply("female"));
- java.util.function.Supplier<T>--------不接收参数,提供T对象的创建工厂,直接通过get()获取指定类型的对象
Supplier<String> sup = ()->{
return UUID.randomUUID().toString();
};
System.out.println(sup.get());
System.out.println(sup.get());
- java.util.function.UnaryOperator<T>--------接收参数对象T,执行业务处理后,返回更新后的T对象
UnaryOperator<String> un = (String str)->{
return str.toUpperCase();
};
System.out.println(un.apply("jijfshdfiUP"));
- java.util.function.BinaryOperator<T>--------接收两个T对象,执行业务处理后,返回一个T对象结果
BinaryOperator<Integer> bi = (Integer a,Integer b)->{
return a>b?a:b;
};
System.out.println(bi.apply(5,7));