1.什么是lambda
lambda表达式被称为箭头函数,匿名函数或闭包
lambda表达式体现的是一种轻量级函数式编程思想
lambda箭头符号(->)的意思是:
左侧是操作的参数
右侧是操作的表达式
public static void main(String[] args) {
//1.传统模式下,新线程的创建
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("threading..." + Thread.currentThread().getId());
}
}).start();
//2.jdk8新特性,lambda表达式优化新线程
new Thread(()->{
System.out.println("threading..." + Thread.currentThread().getId());
}).start();
}
2.lambda 表达式的常用语法
2.1 函数式接口(function interface)
什么是函数式接口:
jdk8 一个新的语义的术语
函数式接口,他就是java类型只包含一个接口方法的特殊接口。
对于函数式接口,jbk8提供了一个语义化检测的注解:@FunctionalInterface
JAVA中的lambda表达式就是函数是接口的一个实现
//1.默认方法 getCredential 为接口中定义的一个默认方法
IUserCredential iUserCredential = new UserCredentialImpl();
System.out.println(iUserCredential.versifyUser("admin"));
System.out.println(iUserCredential.getCredential("admin"));
String msg = "hello word";
//2.静态方法 verifyMessage 为接口定义的一个静态方法
if(IMessageFormat.verifyMessage(msg)){
IMessageFormat mf = new MessageFormatImpl();
System.out.println(mf.format("hello","json"));
}
//3.匿名内部类 实现接口的抽象方法
IUserCredential ic = new IUserCredential() {
@Override
public String versifyUser(String userName) {
return "admin".equals(userName)?"ic + 管理员":"ic + 会员";
}
};
System.out.println(ic.versifyUser("admin"));
System.out.println(ic.versifyUser("manager"));
//4.lambda表达式 针对函数是接口的实现 lambda 表达式 等号后面的括号对应方法参数的括号
IUserCredential ic2 = (String userName)->{
return "admin".equals(userName)?"lbd + 管理员":"lbd + 会员";
};
System.out.println(ic2.versifyUser("admin"));
System.out.println(ic2.versifyUser("manager"));
2.1.1 lambda 表达式常用的java自带函数接口(java.util.function提供了大量的函数式接口)
- Predicate 接收参数T对象,返回一个boolean类型结果
- Consumer 接收参数T对象,没有返回值
- Function 接收参数T对象,返回R对象
- Supplier 不接受任何参数,直接通过get()获取指定类型的对象
- UnaryOperator 接口参数T对象,执行业务处理后,返回更新后的T对象
- BinaryOperator 接口接收两个T对象,执行业务处理后,返回一个T对象
//接收T 返回T
UnaryOperator<String> uo = (String name)->{
return name + "返回T";
};
2.1 lambda语法及使用
1)声明:就是和lambda表达式绑定的接口类型
2)参数:包含在一对圆括号中,和绑定的接口中的抽象方法中的参数个数及顺序一致。
3)操作符:->
4)执行代码块:包含在一对大括号中,出现在操作符号的右侧
[接口声明] = (参数) -> {执行代码块};
lambda表达式语法注意事项
1. lambda表达式,必须和接口进行绑定。
2. lambda表达式的参数,可以附带0个到n个参数,括号中的参数类型可以不用指定,jvm在运行时,会自动根据绑定的抽象方法中电参数进行推导。
3. lambda表达式的返回值,如果代码块只有一行,并且没有大括号,不用写return关键字,单行代码的执行结果,会自动返回。
如果添加了大括号,或者有多行代码,必须通过return关键字返回执行结果。
- 代码示例:
// 没有参数,没有返回值的lambda表达式绑定的接口
interface ILambda1{
void test();
}
// 带有参数,没有返回值的lambda表达式
interface ILambda2{
void test(String name, int age);
}
// 带有参数,带有返回值的lambda表达式
interface ILambda3 {
int test(int x, int y);
}
ILambda1 i1 = () -> {
System.out.println("hello word!");
};
i1.test();
//lambda表达式 如果只有一行代码可以不用写 大括号 {}
ILambda1 i2 = () -> System.out.println("hello word");
i2.test();
ILambda2 i21 = (String n, int a) -> {
System.out.println(n + "say: my year's old is " + a);
};
i21.test("jerry", 18);
//lambda表达式可以不用写 数据类型jvm运行时候 会自动根据接口绑定的参数进行推导出来
ILambda2 i22 = (n, a) -> {
System.out.println(n + " 说:我今年" + a + "岁了.");
};
i22.test("tom", 22);
ILambda3 i3 = (x, y) -> {
int z = x + y;
return z;
};
System.out.println(i3.test(11, 22));
// lambda表达式的返回值,如果代码块只有一行,并且没有大括号,不用写return关键字
ILambda3 i31 = (x, y) -> x + y;
System.out.println(i31.test(100, 200));
- lambda表达式类型检查:jvm会根据代码 自动检测到lambda表达式关联的接口
public class APP3 {
public static void test(MyInterface<String,List> inter){
List<String> stringList = inter.strategy("hello",new ArrayList());
System.out.println(stringList);
}
public static void main(String[] args) {
test(new MyInterface<String, List>() {
@Override
public List strategy(String s, List list) {
list.add(s);
return list;
}
});
/*
(x,y)---> test(param) --->param==MyInterface ---> 从而推导lambda表达式的类型为 MyInterface类型
这个就是对lambda表达式的类型检查,MyInterface接口就是lambda表达式的目标类型(traget typing)
通过MyInterface 的传参 jvm会推导出x,y
(x,y)->{..} --> MyInterface.strategy(T r, R r)--> MyInterface<String, List> inter
--> T==String R==List --> lambda--> (x, y) == strategy(T t , R r)--> x==T==String y==R==List
lambda表达式参数的类型检查
*/
test((x,y)->{
y.add(x);
return y;
});
}
}
@FunctionalInterface
interface MyInterface<T,R>{
R strategy(T t,R r);
}
2.3 lambda表达式运行的原理
lambda表达式在JVM底层解析成私有静态方法和匿名内部类
通过 匿名内部类的接口方法 来调用静态方法实现
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200716194332752.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2R5eTAyMTM=,size_16,color_FFFFFF,t_70#pic_center)
2.4 Stream的作用
Stream常见操作API介绍
-
聚合操作
-
stream的处理流程
数据源
数据转换
获取结果 -
获取Stream对象
- 从集合或者数组中获取[**]
Collection.stream(),如accounts.stream()
Collection.parallelStream()
Arrays.stream(T t) - BufferReader
BufferReader.lines()-> stream() - 静态工厂
java.util.stream.IntStream.range()…
java.nio.file.Files.walk()… - 自定构建
java.util.Spliterator - 更多的方式…
Random.ints()
Pattern.splitAsStream()…
- 从集合或者数组中获取[**]
-
中间操作API{intermediate}
操作结果是一个Stream,中间操作可以有一个或者多个连续的中间操作,需要注意的是,中间操作
只记录操作方式,不做具体执行,直到结束操作发生时,才做数据的最终执行。
中间操作:就是业务逻辑处理。
中间操作过程:无状态:数据处理时,不受前置中间操作的影响。
map/filter/peek/parallel/sequential/unordered
有状态:数据处理时,受到前置中间操作的影响。
distinct/sorted/limit/skip -
终结操作|结束操作{Terminal}
需要注意:一个Stream对象,只能有一个Terminal操作,这个操作一旦发生,就会真实处理数据,生成对应的处理结果。
终结操作:非短路操作:当前的Stream对象必须处理完集合中所有 数据,才能得到处理结果。
forEach/forEachOrdered/toArray/reduce/collect/min/max/count/iterator
短路操作:当前的Stream对象在处理过程中,一旦满足某个条件,就可以得到结果。
anyMatch/allMatch/noneMatch/findFirst/findAny等
Short-circuiting,无限大的Stream-> 有限大的Stream。