个人理解:Lambda表达式是一种简洁高效的实现匿名内部类的一种方式.可以使代码变得更清晰、更灵活.大大增加代码可读性.
下面进行匿名内部类和Lambda表达式的比较,效果一目了然.
在java8之前使用匿名内部类是这样的
public void Test3() {
List<Student> list = fitterStudent(students, new MyPredicate<Student>() {
@Override
public boolean judge(Student stu) {
return stu.getSex().equals("男");
}
});
}
可以看到真正有用的只有return stu.getSex().equals("男");
这一行代码,但是因为格式,确不得不把其他的好多行都写出来,毫无疑问这样的话,代码的可读性会大大降低.
下面来看一下使用Lambda表达式的效果
public void Test2() {
List<Student> list = fitterStudent(students, (stu) -> stu.getSex().equals("女"));
}
看到效果了吧,原来的6
行代码,现在只需要1
行.是不是很6…
效果看到了,下面介绍Lambda表达式的基本语法
java8中引入一个新的操作符"->",称为箭头操作符或者为lambda操作符
箭头操作符将拉lambda表达式拆分成两个部分
左侧:参数列表,所实现接口抽象方法的参数列表(函数式接口)
右侧:所需执行的功能,称为lambda体
lambda表达式需要"函数式接口"(接口中只有一个抽象方法)
支持 可以使用注@FunctionalInterface 帮忙检查是否是函数式接口
-
语法格式一: 无参数,无返回值
public void Test1() {
Runnable r1 = () -> System.out.println("Hello Lambda!");
r1.run();
}
-
语法格式二: 有一个参数,无返回值
public void Test2() {
Consumer<String> con = (x) -> System.out.println(x);
con.accept("我是莫提!");
}
-
语法格式三: 若只有一个参数则参数的小括号可以不写,(推荐还是写上)
public void Test3() {
Consumer<String> con = x -> System.out.println(x);
con.accept("我是莫提!");
}
-
语法格式四: 有多个参数,并且lambda体中有多个语句,并且有返回值
public void Test4() {
Comparator<Integer> com = (x,y) -> {
System.out.println("有多个参数,并且lambda体中有多个语句,必须使用大括号,并且有返回值");
return Integer.compare(x, y);
};
System.out.println(com.compare(520, 1314));
}
-
语法格式五: 有多个参数并且有返回值,只有一条语句(return 和大括号都可以省略)
public void Test5() {
Comparator<Integer> com = (x,y) -> Integer.compare(x, y);
System.out.println(com.compare(520, 1314));
}
-
语法格式六: lambda表达式的参数列表数据类型可以不写,jvm自动推断(推荐不写)
public void Test5() {
Comparator<Integer> com = (Integer x,Integer y) -> Integer.compare(x, y);
System.out.println(com.compare(520, 1314));
}
总结:
左右遇一括号省
'->‘左边参数列表中若只有一个参数,那么小括号可以省略,’->'右边如果只有一条语句,那么大括号可以省略
左侧推断类型省
'->'左边参数的参数类型可以省略
右侧一条return省
如果Lambda表达式具有返回值,并且只有一条语句,那么可以省略’return’关键字
Lambda表达式既然这么好用,那么是不是什么时候都可以应用呢?
不是的,Lambda表达式必须要有函数式接口的支持,即接口中必须只有一个抽象方法
那么问题来了,难道每次使用Lambda表达式都需要自己写一个函数式接口?
当然不是了,java8现在内置了四大基本的函数式接口,而且还有好多函数式接口,所以没有想象的那么麻烦,下面就开始介绍java8内置的四大函数式接口
一. Consumer<T> 消费型接口(有一个参数,但是无返回值) void accept(T t);
@Test
public void test1() {
happy(20000, (money) -> System.out.println("我今天花了"+money+"元"));
}
public void happy(double money,Consumer<Double> consumer) {
consumer.accept(money);
}
二. Supplier<T> 供给型接口(无参数,但是有返回值) T get();
@Test
public void Test2() {
List<Integer> numList = getRandomNum(20, () -> (int)(Math.random()*100));
numList.forEach(System.out::println);
}
public List<Integer> getRandomNum(int num,Supplier<Integer> sup){
List<Integer> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
list.add(sup.get());
}
return list;
}
三. Function<T,R> 函数型接口(有一个参数,有返回值) R apply(T t);
@Test
public void Test3() {
String result = strHandler("My name is ", (str) -> {
return str+= "Moti";
});
System.out.println(result);
}
public String strHandler(String str,Function<String, String> fun) {
String resultStr = fun.apply(str);
return resultStr;
}
四. Predicate<T> 断言型接口(有一个参数,返回值为波尔类型) boolean test(T t);
@Test
public void Test4() {
List<String> list = Arrays.asList("Hello","world","MY","NAME","IS","MOTI");
List<String> result = filterStr(list, (str) -> {
return str.equals("Hello")||str.equals("world");
});
result.forEach(System.out::println);
}
public List<String> filterStr(List<String> list,Predicate<String> pre){
List<String> resultList = new ArrayList<>();
for (String string : list) {
if(pre.test(string)) {
resultList.add(string);
}
}
return resultList;
}
Java8 还有好多关于以上接口的子接口,有兴趣的可以自己去查查
以上就是目前为止我所了解的Lambda表达式,才疏学浅,以后还会来更新(第一次写博客,多多见谅)