什么是lambda表达式:
lambda表达式是一个匿名函数,即没有函数名的函数。Java8使用lambda表达式来代替匿名类,使代码更加简洁
是一段可以传递的代码,主要使用的是箭头操作符 。
左侧:Lambda (参数列表)
右侧:函数实现的功能,如果超过一句代码,用大括号括起来
lambda表达式依赖于接口的支持,(函数式接口:只存在一个抽象方法的接口,可以使用@FunctionalInterface注解进行标记)
所以,在我们使用之前,需要先创建接口
* lambda表达式的语法格式
* 语法格式一: 无参数 无返回值
public interface OneInterface {
void print();
}
@Test
public void test1() {
Employee emplyee = new Employee("电脑端",23,36000.2);
test(() -> System.out.println(emplyee.getName())); //接口无参数无返回值
}
public void test(OneInterface interface1) {
interface1.print();
}
* 语法格式二:有参数,无返回值 (x)->System.out.println(x)
* 语法格式三: 若只有一个参数,参数的小括号可以不写 x->System.out.println(x)
@Test
public void test2(){
//这里仅仅是一个实现,实现consumer的抽象方法
Consumer con = x->System.out.println(x);
//这里使用的是Java现有的接口,只有一个抽象方法
con.accept(8);
}
相当于等号后边是一个匿名类的实现。
* 语法格式四:有两个参数,并有返回值,方法体不止一条语句 多条语句用哪个大括号括起来
@Test
public void test3(){
BiFunction fun = (x,y)-> {
if(y>x){
return (int) (y-x);
}else{
return (int) (x-y);
}
};
System.out.println(fun.apply(35L, 78L));
}
* 语法格式五:若lambda体内只有一条语句,大括号和return可以省;
@Test
public void test4(){
Supplier supplier = ()-> Math.random()*100;
System.out.println(supplier.get());
}
* 语法格式六:lambda表达式的参数列表的参数类型可以不写,JVM编译器会根据上下文推断数据类型,即“类型推断”;
总结: 左右遇一括号省
* 左侧推断类型省
* 超过一句括号扩
* 不超就把return省
*
* 能省则省
以上是lambda表达式的基本形式,但是现在我们发现虽然lambda表达式让我们的代码更加简洁了,但是每次使用都需要产生新的接口,并没有减轻我们的工作量。所以Java为我们提供了
四大基础函数式接口
Consumer
@Test
public void test(){
Consumer consumer = (x)->System.out.println("消费了"+ x +"元");
consumer.accept(5200.0);
}
Supplier
@Test
public void test01(){
Random random = new Random(47);
Supplier get = ()->random.nextDouble();
for (int i = 0; i < 10; i++) {
System.out.println(get.get());
}
}
Function
@Test
public void test02(){
Function fun = (x)->x.trim();
String newString = fun.apply(" 56dsf sd ");
System.out.println(newString);
Function fun2 = (x)-> x.toUpperCase();
String newstr = fun2.apply("asdsfg");
System.out.println(newstr);
}
Predicate
@Test
public void test0(){
Predicate judge = (x) -> x >300;
System.out.println(judge.test(3650));
}
方法引用:若lambda体内的方法已经有方法实现了,我们可以使用方法引用,可以理解为方法引用时lambda表达式的另一种方式。也就是对已存在方法的一次调用
主要有三种格式: *类::实例方法名
*对象::实例方法名: 因为println方法已经存在了,方法体中包含println方法,直接可以进行方法引用,println方法是 PrintStream的非静态
方法,使用对象进行引用 out::println (对象::方法名)
@Test
public void test01(){
PrintStream out = System.out;
Consumer consumer = (x)->out.println(x);
Consumer con = out::println;
consumer.accept("DNFhsziudfh");
System.out.println("————————");
con.accept("DNFhsziudfh");
}
*类::静态方法名 int compare(T o1, T o2); 在Lambda体中使用Integer.compare方法,,并且compare方法所需的参数和 接口的参数列表相同,可以使用方法引用,cmpare方法是静态方法 使用类::方法名称 Integer::compare
@Test
public void test02(){
Comparator com = (x,y) -> Integer.compare(x, y);
Comparator com1 = Integer::compare;
System.out.println(com.compare(2, 8));
System.out.println(com1.compare(5, 6));
}
我们都知道前两种格式,和我们平时使用方法调用是相似的,但是第三种是,类::实例方法名,我们知道的类只能调用静态方法,所以这种格式是有条件的当接口的参数列表的第一个参数是已存在的方法的调用者,第二个参数是方法的参数时,可以写成类::实例方法名的这种调用
@Test
public void test03(){
BiPredicate bi = (x,y) -> x.equals(y);
BiPredicate bi2 = String::equals;
System.out.println(bi.test("as", "as"));
System.out.println(bi.test("as1", "as"));
}
构造器引用 就是在函数体存在对某个对象的构造时,可以转换成构造器引用的形式
*类名::new
lambda体内存在对Emplyee类的构造,可以转换成构造器引用形式而所调用的构造函数,是根据接口方法的参数列表类型确定的
@Test
public void test04(){
Supplier sup = ()->new Employee();
Supplier sups = Employee::new;
Function fun =Employee::new;
System.out.println(fun.apply("张三"));
}
数组引用:与构造函数引用类似
@Test
public void test05(){
String [] str = new String [3];
Function fun = String[]::new;
fun.apply(3);
}