Lamdba表达式由JavaSE8提供,它允许我们把函数作为一个方法的参数传入,可以认为是匿名内部类(类限定为函数式接口)的简化形式,能够帮助我们简化代码,优化代码结构,lamdba表达式也称之为闭包
基本语法:
(参数列表) ->{方法体 }
(parameters) -> expression 或 (parameters) ->{ statements; }
①参数列表:即函数式接口的形参列表,类型可不声明,括号可省略
②->:lamdba表达式的固定语法,用于链接参数列表和表达式主体,可以理解为“被用于”的意思
③方法体:重写方法的具体实现,可以是表达式或是代码块,当为单个语句(表达式)时{}可省略
interface and {//函数式接口,仅有一个抽象方法的接口
void setAnd(int a, int b);
}
public class Test1 {
public static void main(String[] args) {
//匿名内部类方式
and testA = new and() {
@Override
public void setAnd(int a, int b) {
System.out.println(a+b);
}
};
//lamdba方式
and testB = (c,d) -> System.out.println(c+d);
//测试
testA.setAnd(1, 3);
testB.setAnd(1,3);
}
}
1. 参数类型可以省略,如果需要省略,每个参数的类型都要省略。
and testB = (int c, int d) -> System.out.println(c+d);
and testB = (c,d) -> System.out.println(c+d);
2. 参数的小括号里面只有一个参数,那么小括号可以省略
and testc = (c) -> System.out.println(c);
and testc = c -> System.out.println(c);
3. 如果方法体当中只有一句代码,那么大括号可以省略
and testB = (c,d) -> {System.out.println(c+d);};
and testB = (c,d) -> System.out.println(c+d);
4. 如果方法体中只有一条语句,且是return语句,那么大括号可以省略,且去掉return关键字
aff testF = (c,d) -> {return c+d;};
aff testF = (c,d) -> c+d;
Lamdba表达式和匿名内部类一样都可以访问封闭类内的成员,即在lamdba表达式内同样可以使用部分封闭类的变量和参数
注意的是可捕获的变量包括final修饰的变量,或是未被修改过的变量。
interface and {//函数式接口,仅有一个方法的接口
void setAnd(int a, int b);
}
public class Test1 {
public static void main(String[] args) {
//final修饰的变量
final int a = 10;
//lamdba方式,可调用fianl修饰的变量a
and testB = (c,d) -> System.out.println(c+d+a);
testB.setAnd(1,3);
}
}
public class Test1 {
//未被修改过的成员变量
public int s = 20;
public void text() {
and testB = (c,d) -> System.out.println(c+d+s);
}
public static void main(String[] args) {
//未被修改过的
int a = 10;
//lamdba方式,可调用fianl修饰的变量a
and testB = (c,d) -> System.out.println(c+d+a);
testB.setAnd(1,3);
}
}
为了能够让Lambda和Java的集合类集更好的一起使用,集合当中,也新增了部分接口和方法,以便与Lambda表达式对接(很多,仅列举集合框架相关常用)
collection接口是Java集合框架的一个顶层接口,提供的forEach()方法可以用来对集合类中的每个元素进行遍历并进行相应的操作,源码如下:
//对每个元素执行action.accept()操作
default void forEach(Consumer super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
在源码中可以看到action类作为forEach()方法的形参对集合类的每个元素都执行了accept()方法,而action是一个函数式接口,是可以使用Lamadba表达式的。
forEach方法的作用就显而易见了,例如可以通过Lamdba表达式重写action的accept方法来对集合类进行遍历输出。
List list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.forEach( a -> System.out.print(a) );
其他用法比一一赘述,请自行摸索
List接口提供的sort方法可以根据我们提供的排序规则对集合类进行排序,源码如下:
public void sort(Comparator super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
排序的比较方法是返回正负值判断的大小,如a、b两个参数a-b>0则认为a>b
对于逆序排序我们可以这样写:
List list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.sort((a,b) -> b-a);
list.forEach(a -> System.out.print(a));
对于字符串根据长短排序我们可以这样写:
List list = new ArrayList<>();
list.add("buffer");
list.add("hello");
list.add("bet");
list.add("As");
list.sort((a,b) -> a.length()-b.length());
list.forEach(a -> System.out.println(a));
和Collection接口的forEach方法类似,同样是对Map中每个映射执行action.accept()方法,源码如下:
default void forEach(BiConsumer super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
可以实现对输出每个映射:
Map map = new HashMap<>();
map.put("1",1);
map.put("2",2);
map.put("3",3);
map.put("4",4);
map.put("5",1);
map.forEach((a,b) -> System.out.println(a + "=" + b));
函数式接口:在Java中指一个接口中仅有一个抽象方法的接口。(default修饰的方法不包含在内,可以和抽象方法并存,lamdba不会报错)
interface and {//函数式接口,仅有一个方法的接口
void setAnd(int a, int b);
}
如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的
@FunctionalInterface
interface and {//函数式接口,仅有一个方法的接口
void setAnd(int a, int b);
default void test() {
System.out.println("JDK1.8新特性,default默认方法可以有具体的实现");
}
}
博主是Java新人,每位同志的支持都会给博主莫大的动力,如果有任何疑问,或者发现了任何错误,都欢迎大家在评论区交流“ψ(`∇´)ψ
优雅美丽的Lamdba----