Lambda表达式概述
lambda表达式时jdk1.8新特性。
函数式编程思想
java从诞生之日就一直倡导“一切皆对象”,但现在java不但支持OOP,还支持面向函数编程(OOF),面向函数编程就是只是重视结果不重视过程
Lambda表达式和匿名内部类的区别:
所需类型不同:
匿名内部类可以是内部类,可以是抽象类,也可以是接口
Lambda表达式只能是接口
使用限制不同:
Lambda表达式使用的接口要求有且仅有一个抽象方法
匿名内部了使用的接口可以有多个方法
实现原理不同:
采用匿名内部类编译后会生成单独的.class文件
采用Lambda表达式不会单独生成.class文件
Lambda表达式的使用
语法
Lambda表达式本质就是匿名函数,在函数的语法中包含返回值类型,方法名,形参列表和方法体。而在Lambda表达式我们只需要关注形参列表和方法体即可。在java语言中,Lambda表达式语法为:(形参列表)->{方法体} ,其中->为lambda操作符或者箭头操作符,形参列表为对应接口实现类中的重写方法的形参列表 ,“方法体”为形参列表重写方法的方法体
使用
- 无返回值的函数式接口
(1)无返回值无参数
/**
* Lambda表达式使用
* 关于无返回值无参数的函数式接口
*/
public class LambdaTest03 {
public static void main(String[] args) {
//匿名内部类的方式改成Lambda表达式
NoParameterNoReturn npnr = new NoParameterNoReturn() {
@Override
public void test() {
System.out.println("无返回值 无参数test方法执行");
}
};
npnr.test();
//改成Lambda表达式
NoParameterNoReturn npnr2 = ()->{
System.out.println("无返回值 无参数test方法执行");
};
npnr2.test();
}
}
@FunctionalInterface
interface NoParameterNoReturn{
void test();
}
(2)无返回值一个参数
public class LambdaTest04 {
public static void main(String[] args) {
//匿名内部类的方式
OneParameterNoReturn opnr = new OneParameterNoReturn() {
@Override
public void test(Integer value) {
System.out.println(value);
}
};
opnr.test(100);
//Lambda 表达式方式
OneParameterNoReturn opnr2 = (Integer value)->{
System.out.println(value);
};
opnr.test(200);
}
}
interface OneParameterNoReturn{
void test(Integer value);
}
(3)无返回值多个参数
public class LambdaTest05 {
public static void main(String[] args) {
MoreParameterNoReturn mpnr = new MoreParameterNoReturn() {
@Override
public void test(Integer v1, Integer v2) {
System.out.println(v1 + v2);
}
};
mpnr.test(1,2);
MoreParameterNoReturn mpnr2 = (Integer v1,Integer v2)->{
System.out.println(v1+v2);
};
mpnr2.test(2,3);
}
}
interface MoreParameterNoReturn{
void test(Integer v1,Integer v2);
}
- 有返回值的函数式接口
(1)有返回值无参数
(2)有返回值一个参数
(3)有返回值多个参数
Lambda表达式语法精简
1. 形参可以省略,如果需要省略,则每个形参类型都要省略
2. 如果形参列表只存在一个参数,那么形参类型和小括号都可以省略
3. 如果方法体只有一行语句,那么方法体的大括号也可以省略
4. 如果方法体只有一条return语句,那么大括号可以省略,且必须去掉return语句
四个基本函数式接口
为了迎合java8函数式接口
jdk增加了四个函数式接口
名字 | 接口名 | 对应抽象方法 |
---|---|---|
消费 | Constumer<T,> | void accept(T t) |
生产 | Supplier<T,> | T get(); |
转换 | Funtion<T,R> | R apply(t t); |
判断 | Predicate<T,> | boolean test(T t) |
以上函数式接口在java.util.function。
Lambda表达式的方法引用
实例方法引用
特点:在Lambda表达式的方法体中,通过对象来调用指定的某个“实例方法”。
要求:函数式接口中抽象方法的返回值类型和形参列表与内部通过调用某个实例方法的返回值类型和形参列表保持一致。
//创建一个生产接口
//匿名内部类方式
Teacher teacher = new Teacher("lao");
Supplier<String> supplier = new Supplier<String>() {
@Override
public String get() {
return teacher.getName();
}
};
System.out.println(supplier.get());
//以上是否符合“实例方法引用”的条件?
Supplier<String> supplier1 = () -> teacher.getName();
System.out.println(supplier1.get());
//使用实例方法引用精简
Supplier<String> supplier2 = teacher::getName;
System.out.println(supplier.get());
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer.accept("sad");
//修改为lambda表达式
Consumer<String> consumer1 = s -> System.out.println(s);
//使用实例方法引用精简
Consumer<String>consumer2 = System.out::println;
consumer2.accept("dasdas");
静态方法引用
要求:函数式接口中的抽象方法的返回值类型和形参列表与内部通过类名调用某个静态方法的返回值类型和形参列表保持一致。
特殊方法引用
要求:把函数式接口中抽象方法的第一个形参作为方法的调用者对象,并且从第二个形参开始可以对应被调用实例方法的参数列表,并且返回值型保持一致
构造方法引用
public class LambdaTest08 {
public static void main(String[] args) {
//条件:函数式接口中的抽象方法第一个参数作为内部方法调用对象
Function<String, Person> function = new Function<String, Person>() {
@Override
public Person apply(String s) {
return new Person(s);
}
};
System.out.println(function.apply("das"));
//Lambda表达式
Function<String,Person> function1 = s -> new Person(s);
System.out.println(function1.apply("dsa"));
//使用构造方法精简
Function<String,Person> function2 = Person::new;
}
}
数组引用
public class LambdaTestr09 {
public static void main(String[] args) {
Function<Integer,int[]>function = new Function<Integer, int[]>() {
@Override
public int[] apply(Integer integer) {
return new int[integer];
}
};
//使用Lambda表达式
Function<Integer,int[]> function1 = length->new int[length];
int[] apply = function1.apply(20);
System.out.println(Arrays.toString(apply));
//使用简单方式
Function<Integer,int[]> f = int[]::new;
f.apply(33);
}
}