关于Lambda表达式:
首先介绍函数式接口的概念:
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口里允许定义默认方法
函数式接口里允许定义静态方法
函数式接口里允许定义java.lang.Object里的public方法
函数式接口可以被隐式转换为lambda表达式。
函数式接口可以现有的函数友好地支持 lambda。
Lambda表达式使用的前提是要用到函数式接口上。
加不加@FunctionalInterface对于接口是不是函数式接口没有影响,该注解只是提醒编译器去检查该接口是否仅包含一个抽象方法。
Java中的lambda无法单独出现,它需要一个函数式接口来盛放,lambda表达式方法体其实就是函数接口的实现.
1.Lambda表达式语法:
创建一个集合:
List<String> names = new ArrayList<String>();
names.add("Google ");
names.add("Runoob ");
names.add("Taobao ");
names.add("Baidu ");
names.add("Sina ");
Java7实现比较器:
// 使用 java 7 排序
private void sortUsingJava7(List<String> names){
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
}
Java8实现比较器:
// 使用 java 8 排序
private void sortUsingJava8(List<String> names){
Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
}
使用Java7和Java8创建的比较器对List集合进行排序,得到的结果都是一样的,Java8使用了Lambda表达式,免去了使用匿名方法的麻烦,消除代码冗余度。
原来传递给比较器方法的参数需要实现一个接口并定义其中的方法,如果使用Java8的Lambda表达式来代替,那么直接在小括号中定义两个参数(不需要指定参数类型,因为Java8会自动判断),这两个参数将用在后面定义的方法中。
(参数1,参数2) -> 参数1.方法名(参数2) 用这种方式来代替Java7中的直接new接口的方式。其中箭头后面调用的方法是原来所要实现的接口中定义的方法中最后返回时所调用的方法。
lambda表达式我们可以理解对于函数式接口和其中的抽象方法的具体实现。
2.Lambda表达式中的变量作用域:
可以在Lambda表达式中使用外面定义的局部变量:
public class Java8Tester {
public static void main(String args[]) {
final int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2); // 输出结果为 3
}
public interface Converter<T1, T2> {
void convert(int i);
}
}
使用时需要注意以下几点:
(1) lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)。如:
int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
num = 5;
//报错信息:Local variable num defined in an enclosing scope must be final or effectively
final
(2)在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。如:
String first = "";
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length());
//编译会出错,Lambda表达式中定义的两个参数中其中有一个参数名为first,与局部变量定义的参数名相同
3.方法引用
当Lambda表达式中只是执行一个方法调用时,不用Lambda表达式,直接通过方法引用的形式可读性更高一些。方法引用是一种更简洁易懂的Lambda表达式。
注意方法引用是一个Lambda表达式,其中方法引用的操作符是双冒号"::"。
方法引用的真实的参数拷贝自函数式接口中抽象方法的参数。表达式体实际调用实现函数式接口的那个类中对应的方法。相当于先自定义一个函数式接口,再写一个方法需要传入该函数式接口类型的参数,然后使用的时候用Lambda表达式的方法引用方式传入其它类的方法(该方法实现了函数式接口中的方法)。
方法引用具体介绍以及方法引用与Lambda表达式的具体关系可以看下面的博客:
https://www.cnblogs.com/xiaoxi/p/7099667.html