目录
函数式编程思想概述
概述:就是拿什么东西就做什么事,就像y=2x+1,输入不同的x就有不同的y,面向对象过分强调必须以对象的形式来做事情,而函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以什么形式做
传统代码的冗余分析
冗余的Runnable代码:
传统写法
public class RunnableImpl implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"创建了一个新的线程执行");
}
public static void main(String[] args) {
TraditionalRunnable tR=new TraditionalRunnable();
Thread t=new Thread(tR);
t.start();
//简化为匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"匿名内部类的方式创建的新线程!");
}
}).start();
}
/*
代码分析:
Thread类需要Runnable接口作为参数,其中的抽象run用来指定线程任务
为指定一个run方法体,不得不需要Runnable接口的实现类
为了省去定义一个Runnable实现类的麻烦,不得不使用匿名内部类
必须重写覆盖抽象run方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错
而实际上,似乎只有方法体才是关键所在!
这里面有很多冗余的代码
*/
}
所以转化编程思想:将run方法体内的代码传递给Thread类知晓
jdk1.8开始加入了Lambda表达式的新特性
Lambda的更优写法
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"通过Lambda表达式创建的线程");
}).start();
匿名内部类的好处与弊端:
优点:帮我们省去实现类的定义
缺点:复杂
语义分析:
无参数
无返回值
代码块
同样的语义体现在Lambda语法中更加简单
()->System.out.println("多线程执行!")
前面的一对小括号即run方法的参数(无),代表不需要任何条件
中间的一个箭头代表将前面的参数传递给后面的代码
后面输出语句即3业务逻辑代码
Lambda标准格式
Lambda标准格式
由三部分组成
一些参数
一个箭头
一段代码
(参数类型 参数名称)->{代码语句}
解释说明格式:
():接口中抽象方法的参数列表,没有参数,就空着;有参数就写出参数,多个参数用逗号分隔
->传递的意思,把参数传递给方法体{}
{}:重写接口的抽象方法的方法体
使用案例
public static void main(String[] args) {
Person[]arr={
new Person("name1",18),
new Person("name2",17),
new Person("name3",20)
};
Arrays.sort(arr, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
for (Person person : arr) {
System.out.println(person);
}
//Lambda写法
Arrays.sort(arr,(Person o1,Person o2)->{
return o1.getAge()-o2.getAge();
});
for (Person person : arr) {
System.out.println(person);
}
Lambda省略格式
Lambda表达式:是可推导,可省略
凡是根据上下文推导出来的内容,都可以省略
可以省略的内容:
1、(参数列表):括号中的参数列表的数据类型可以省略不写
2、(参数列表):括号中的参数如果只有一个,那么类型和()都可以省略
3、{一些代码}:如果{}中代码只有一行,无论是否有返回值,都可以省略{}、return、分号,必须一起省略
例子省略;和{}后
new Thread(()->
System.out.println(Thread.currentThread().getName()+"通过Lambda表达式创建的线程")
).start();
省略;和{}、return、参数类型的案例
Arrays.sort(arr,( o1, o2)->
o1.getAge()-o2.getAge()
);
使用Lambda的前提:
1、使用Lambda必须有接口,且要求接口中有且仅有一个抽象方法
无论是jdk内置的接口还是自己定义的,只有接口中抽象方法存在且唯一才能用
2、使用Lambda必须具有上下文推断
也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例
备注:有且仅有一个抽象方法的接口,称为函数式接口