灵魂三问:Lambda表达式是什么?用来做什么?怎么使用?
首先来谈论Lambda表达式是用来做什么的?对于Lambda表达式是什么,怎么使用后面一起总结学习
问题一:Lambda表达式时用来做什么的,也就是Lambda表达式的作用?
Lambda表达式是用来简化函数式接口的实现,从而简化我们的开发。有且仅有一个抽象方法的接口被称之为函数式接口,函数式接口可以使用@FunctionalInterface注解修饰。
对比我们已知的实现接口的方式:1、使用implements关键字来实现接口。2、使用内部类的方式实现接口
首先定义一个只有一个方法的接口:
@FunctionalInterface
public interface People {
public void sayHello();
}
1)、使用implements方式来实现接口,代码示例如下
public class Student implements People {
@Override
public void sayHello() {
System.out.println("hello java8新特性");
}
}
@Test
public void test(){
Student stu=new Student();
stu.sayHello();
}
2)、使用内部类的方式来实现接口,代码示例如下:
@Test
public void test1(){
People people=new People() {
@Override
public void sayHello() {
System.out.println("hello java8新特性");
}
} ;
people.sayHello();
}
3)、使用Lambda表达式来实现接口,代码示例如下:
@Test
public void test2(){
People people=()-> System.out.println("hello java8新特性 -- Lambda表达式");
people.sayHello();
}
对比发现Lambda表达式对于只有一个抽象方法的接口实现,它大大的简化了我们开发。如果它的作用仅限于此的话,个人觉得它的作用并不明显或者说Lamda表达式没有多大的作用,而它真正的强大之处,个人觉得是配合java8的另一个新特性Stream API进行使用,简化对集合和数组的操作。Stream API这个新特性在之后的博客中会进行介绍
问题二:Lambda表达式是什么?其使用格式?
Lambda表达式的语法格式:()->{}
Java8中引入了一个新的操作符“->”该操作符称之为箭头操作符或者Lambda操作符,将Lambda表达式拆分成两部分。
左侧:Lambda表达式参数列表
右侧:Lambda表达式中所执行的功能,即Lambda表达式
格式一:无参无返回值
()-> System.out.println("无参无返回值")
代码示例:
@Test
public void test4(){
Runnable runnable=()-> System.out.println("无参无返回值");
runnable.run();
}
格式二:有一个参数,无返回值。
(x)-> System.out.println(x)
代码示例:
@Test
public void test5(){
Consumer consumer=(x)-> System.out.println(x);
consumer.accept("无参无返回值格式");
}
格式三:若只有一个参数,左侧小括号可以不写
x-> System.out.println(x)
代码示例:
@Test
public void test6(){
Consumer consumer=x-> System.out.println(x);
consumer.accept("只有一个参数,左侧的小括号可以省略");
}
格式四:有两个以上参数,且Lambda体中有多条语句
Comparator
System.out.println("有两个以上参数,且有多条语句的格式");
return Integer.compare(x,y);
};
代码示例:
@Test
public void test7(){
Comparator comparator=(x,y)->{
System.out.println("有两个以上参数,且有多条语句的格式");
return Integer.compare(x,y);
};
}
格式五:若Lambda体中只有一条语句,return 和大括号多可以省略
BiFunction
@Test
public void test8(){
BiFunction bf=(x,y)->x+y;
System.out.println(bf.apply(3,4));
}
格式六:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出数据类型,即“类型推断”
BiFunction
@Test
public void test9(){
BiFunction bf=(Integer x,Integer y)->x+y;
System.out.println(bf.apply(3,4));
}
上联:左右遇一括号省
下联:左侧推断类型省
横批:能省则省
Lambda表达式基于函数接口,接下来介绍一下java8提供的四大内置函数式接口和其他扩展型函数式接口
四大内置函数式接口:
一)、Consumer
void accept(T t);
简单示例:
@Test
public void test1(){
shopping(10000,(x)-> System.out.println("wife喜欢淘宝,每次消费"+x+"元"));
}
public void shopping(double money,Consumer consumer){
consumer.accept(money);
}
结果:
二)、Supplier
void get();
简单示例:
@Test
public void test2(){
List numList = getNumList(10, () -> (int) (Math.random() * 100));
System.out.println(Arrays.asList(numList));
}
//随机产生指定个数的整数,放入集合
public List getNumList(int num, Supplier sup){
List list=new ArrayList<>();
for(int i=0;i
运行结果:
三)、Function
R apply(T);
简单示例:
@Test
public void test3(){
String s = strHandle("hello ,javaWord", (x) -> x.toUpperCase());
System.out.println(s);
String s1 = strHandle("hello ,javaWord", (x) -> x.substring(0, 5));
System.out.println(s1);
}
//字符串处理
public String strHandle(String str, Function fun){
return fun.apply(str);
}
运行结果:
四)、Predicate
boolean test(T t);
简单示例:
@Test
public void Test4(){
String[] strs={"hello","word","ok","now","java"};
List list = filterStr(strs, (x) -> x.length() > 3); //长度大于3的数组放入集合
System.out.println(Arrays.asList(list));
List list1 = filterStr(strs, (x) -> x.contains("o"));
System.out.println(Arrays.asList(list1));
}
//需求:所有满足条件的字符串放入集合
public List filterStr(String[] strs, Predicate pd){
List list=new ArrayList<>();
for(int i=0;i
运行结果:
其他的一些扩展接口:
所有的函数式接口都存放在rt.jar 中的java.util.function包中
接下来介绍能对Lambda表达式进行简化操作的相关知识点:1)、方法以引用 2)、构造器引用 3)、数组引用
方法引用:若lambda体中的功能,已经有方法提供了实现。那么可以使用方法引用进行替换。
方法引的三种形式:
1)、简单示例
@Test
public void test1(){
Employee emp=new Employee(100,"刘邦",55,11111.11);
Supplier sup1=()->emp.getName(); //Lambda表达式
System.out.println(sup1.get());
System.out.println("-------使用方法引用进行替换----------");
Supplier sup2=emp::getName; //对象::实例方法名
System.out.println(sup2.get());
}
运行结果
2)、简单示例
@Test
public void test2(){
Comparator com1=(x,y)->Integer.compare(x,y); //Lambda表达式
System.out.println(com1.compare(3,4));
System.out.println("-------使用方法引用进行替换----------");
Comparator com2=Integer::compare; //方法引用: "类名::静态方法名"
System.out.println(com2.compare(4,3));
}
运行结果:
3)、简单示例:
@Test
public void test3(){
BiPredicate bp1=(x,y)->x.equals(y); //Lambda表达式
System.out.println(bp1.test(3,5));
System.out.println("-------使用方法引用进行替换----------");
BiPredicate bp2=Integer::equals; //方法引用: "类名::实例方法名"
System.out.println(bp2.test(4,4));
}
运行结果
注意:
构造器引用:构造器中的参数列表需与函数式接口中的参数列表保持一致,Lambda表达式可以使用构造器引用进行替换
格式: 类名::new
简单示例:
@Test
public void test4(){
Function fu1=(x)->new Employee(x);
System.out.println(fu1.apply("项羽").getName());
System.out.println("---------使用构造器引用进行替换-------------");
Function fu2=Employee::new; //构造器引用 "类名::new"
System.out.println(fu2.apply("范增").getName());
}
运行结果:
数组引用: 类型[] :: new;
简单示例:
@Test
public void test5(){
Function fu1=(x)->new String[10];
System.out.println(fu1.apply(10).length);
System.out.println("---------使用数组引用进行替换-------------");
Function fu2=String[]::new; //构造器引用 "type[]::new"
System.out.println(fu2.apply(10).length);
}
运行结果:
实战练习:
1、使用Collections.sort()方法,通过定制排序比较两个Employee(先按照年龄比,年龄相同,按照姓名比),使用Lambda表达式传递参数
private List emps= Arrays.asList(
new Employee(103,"萧何",44,8888.77),
new Employee(101,"刘邦",55,10000.11),
new Employee(102,"张良",45,9999.99),
new Employee(106,"陈平",33,5555.55),
new Employee(104,"韩信",33,3333.33),
new Employee(105,"周勃",29,6666.66)
);
//使用Collections.sort()方法,通过定制排序比较两个Employee(先按照年龄比,年龄相同,按照姓名比)
@Test
public void test1(){
Collections.sort(emps,(e1,e2)->{
if(e1.getAge()==e2.getAge()){
return e1.getName().compareTo(e2.getName());
}else{
return Integer.compare(e1.getAge(),e2.getAge());
}
});
for (Employee emp:emps){
System.out.println(emp);
}
}
运行结果:
2、编写一个方法,能对两个整数进行加、减、乘、除运算,使用Lambda表达式实现
@Test
public void test2(){
System.out.println("加法运算:"+op(10,2,(x,y)->x+y));
System.out.println("减法运算:"+op(10,2,(x,y)->x-y));
System.out.println("乘法运算:"+op(10,2,(x,y)->x*y));
System.out.println("除法运算:"+op(10,2,(x,y)->x/y));
}
//需求:编写一个方法,能对两个整数进行四则运算,使用Lambda表达式实现
public Integer op(Integer num1, Integer num2, BiFunction bf){
return bf.apply(num1,num2);
}
运行结果:
总结:对Lambda表达式及相关的知识点进行了整理和学习。
本章的知识点:1)、Lambda表达式的作用和使用、
2)、函数式接口以及java8内置的四大核心函数式接口:消费型接口、供给型接口、函数型接口、断言型接口。
3)、方法引用、构造器引用、数组引用。用于对Lambda表达式的简化操作
参考:张长志老师的视频
学无止境,不进则退