一.什么是Lambda
1.Lambda概述
◇Lambda表达式也被称为箭头函数、匿名函数、闭包
◇Lambda表达式体现的是轻量级函数编程思想
◇‘->’ 符号是Lambda表达式核心操作符号,符号左侧是操作参数,符号右侧是操作表达式
◇Lambda是JDK8新特性,对开发环境只支持JDK8及以上版本
2.MCAD模式
◇Model Code as Data,编码及数据,尽可能轻量级的将代码封装为数据。
◇存在问题:语法冗余、this关键字、变量捕获、数据控制等
◇解决方案:接口&实现类(匿名内部类)
3.问题及优化
使用测试用例来展示
需求环境:线程类的创建
解决方案:匿名内部类实现
测试代码如下
package com.example.lambda.test;
/**
* Lambad表达式入门01
*/
public class Demo01 {
public static void main(String[] args) {
//1.传统模式下,新线程的创建
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("threading..."+Thread.currentThread().getId());
}
}).start();
//2.JDK1.8新特性,lambda表达式优化线程模式
new Thread(()->{
System.out.println("lambda..."+Thread.currentThread().getId());
}).start();
}
}
4.为什么要用Lambda
1.它不是解决未知问题的新技术
2.对现有解决方案的语义优化
3.需要根据实际需求考虑性能问题
二.Lambda表达式基础知识
1.函数式接口
函数式接口(function interface)
函数式接口,就是Java类型系统中的接口
函数式接口,是只包含一个接口方法的特殊接口
语义化检测注解:@Functionallnterface
package com.example.lambda.test;
/**
* 用户身份认证标记接口
* 只提供一个接口方法的接口 叫做函数式接口
*
*/
@FunctionalInterface
public interface IUserCredential1 {
/**
* 通过用户账号,验证用户身份信息的接口
* @param userName 用户账号
* @return 返回身份证信息
*/
String verifyUser(String userName);
}
默认接口方法
默认方法实现的场景:是给所有的实现子类的对象增加了一些通用方法
package com.example.lambda.test;
/**
* 用户身份认证标记接口
* 只提供一个接口方法的接口 叫做函数式接口 默认方法不包含其中
*
*/
@FunctionalInterface
public interface IUserCredential {
/**
* 通过用户账号,验证用户身份信息的接口
* @param userName 用户账号
* @return 返回身份证信息
*/
String verifyUser(String userName);
/**
* 新增默认方法 使用default修饰
* @param userName
* @return
*/
default String getCredential(String userName){
//模拟方法
if ("admin".equals(userName)){
return "admin + 系统管理员";
}else if("test".equals(userName)){
return "test + 测试用户";
}else {
return "commons + 普通会员信息";
}
}
}
静态接口方法
package com.example.lambda.test;
/**
* 消息传输格式转换接口
*/
@FunctionalInterface
public interface IMessageFormat {
/**
* 消息转换方法
* @param message 要转换的消息
* @param format 转换的格式 [xml/json..]
* @return 返回转换后的数据
*/
String format(String message,String format);
/**
* 消息合法性验证方法 使用static修饰
* 新增静态方法
* @param msg 要验证的消息
* @return 返回验证结果
*/
static boolean verifyMessage(String msg){
if (msg != null){
return true;
}else {
return false;
}
}
}
默认接口方法和静态接口方法测试
package com.example.lambda.test;
/**
* Lambad表达式入门02
*
* 需求改动:
* 所有的用户验证,可以同时获取用户的验证信息[是否认证成功如果成功返回用户,否则返回null]
*
*/
public class Demo02 {
public static void main(String[] args) {
IUserCredential userCredential=new UserCreadentialImpl();
System.out.println(userCredential.verifyUser("admin"));
//测试默认方法
System.out.println(userCredential.getCredential("admin"));
String msg="hello world";
//静态方法验证消息是否通过
if(IMessageFormat.verifyMessage(msg)){
IMessageFormat messageFormat=new MessageFormatImpl();
messageFormat.format("hello","json");
}
}
}
总结:函数式接口,默认接口方法,静态接口方法都可以共同存在
重点: 特殊情况,来自Object继承方法 也是可以通过的
package com.example.lambda.test;
/**
* 消息传输格式转换接口
*/
@FunctionalInterface
public interface IMessageFormat {
/**
* 消息转换方法
* @param message 要转换的消息
* @param format 转换的格式 [xml/json..]
* @return 返回转换后的数据
*/
String format(String message,String format);
/**
* 消息合法性验证方法 使用static修饰
* 新增静态方法
* @param msg 要验证的消息
* @return 返回验证结果
*/
static boolean verifyMessage(String msg){
if (msg != null){
return true;
}else {
return false;
}
}
/**
* toString 方法
* @return
*/
String toString();
}
java中的lambda表达式,核心就是一个函数式接口的实现
package com.example.lambda.test;
/**
* Lambad表达式入门03
*
*
*/
public class Demo03 {
public static void main(String[] args) {
IUserCredential userCredential = new UserCreadentialImpl();
System.out.println(userCredential.verifyUser("admin"));
//测试默认方法
System.out.println(userCredential.getCredential("admin"));
String msg = "hello world";
//静态方法验证消息是否通过
if (IMessageFormat.verifyMessage(msg)) {
IMessageFormat messageFormat = new MessageFormatImpl();
messageFormat.format("hello", "json");
}
//匿名内部类,实现接口的抽象方法
IUserCredential ic = new IUserCredential() {
@Override
public String verifyUser(String userName) {
return "admin".equals(userName) ? "管理员" : "会员";
}
};
System.out.println(ic.verifyUser("admin"));
System.out.println(ic.verifyUser("test"));
//lambda表达式,针对函数式接口的简单实现 (String userName) 对应匿名内部类的参数 ;->{} 对应方法区域{} ;{}里面输出逻辑
IUserCredential ic2=(String userName) ->{
return "admin".equals(userName) ? "lambda管理员" : "lambda会员";
};
System.out.println(ic2.verifyUser("admin"));
System.out.println(ic2.verifyUser("test"));
}
}
JAVA类型系统内建函数式接口
◇ java.lang.Runable 多线程实现接口
◇ java.lang.Comparable 数据比较接口
◇ java.lang.comparator 数据比较接口
◇ java.io.FileFilter 文件处理接口
jdk8提供了java.util.function包,提供了常用的函数式功能接口
举个例子
单个方法的处理场景:方法的处理无非就是参与方法运算的参数和方法执行后的返回值,jdk1.8针对不同的情况,提供了不同的函数支持
比如说,java.util.function.Predicate
接收参数对象T,返回一个boolean类型结果
java.util.function.Comsumer
接收参数对象T,不返回结果
java.util.function.Function<T,R>
接收参数对象T,返回结果对象R
java.util.function.Supplier
不接收参数,提供T对象的创建工厂
java.util.function.UnaryOperator
接收参数对象T,返回结果对象T
java.util.function.BinaryOperator
接收两个T对象,返回一个T对象结果
代码如下:
package com.example.lambda.test;
import org.springframework.validation.BindingResult;
import sun.misc.PostVMInitHook;
import java.util.UUID;
import java.util.function.*;
/**
* jdk中常见的函数式接口
*/
public class Demo04 {
public static void main(String[] args) {
//判断数据,返回true或者false的时候
Predicate<String> pre=(String userName) -> {
return "admin".equals(userName);
};
System.out.println(pre.test("admin"));
System.out.println(pre.test("test"));
//对一个问题进行功能性处理,不需要任何返回值的时候,可以考虑使用 Consumer
Consumer<String> con=(String msg) -> {
System.out.println("要发送的消息:"+msg);
System.out.println("消息发送完成");
};
con.accept("hello word");
con.accept("lambda 学习");
//场景适用于前台传递一个参数,后台判断为boolean类型的结果,保存到数据库为0或者1来表示
Function<String,Integer> fun=(String gender) -> {
return "male".equals(gender)?1:0;
};
System.out.println(fun.apply("male"));
System.out.println(fun.apply("female"));
Supplier<String> sup=() ->{
return UUID.randomUUID().toString();
};
System.out.println(sup.get());
System.out.println(sup.get());
System.out.println(sup.get());
//可以针对对象,对这个对象做处理并返回
UnaryOperator<String> un=(String img) -> {
img +="100X200";
return img;
};
System.out.println(un.apply("原图--"));
//两个对象做比较,最终返回一个胜出的对象
BinaryOperator<Integer> bo=(Integer i1,Integer i2) ->{
return i1>i2 ? i1:i2;
};
System.out.println(bo.apply(12,13));
}
}
总结:java提供了java.util.function包,这里面提供了大量的函数式接口,这些函数式接口针对不同的场景实现不同的功能