?
?
1、什么是Lambda 表达式Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。
在 Java 语言中,可以为变量赋予一个值。
int a=130; String s="hello world"; Boolean flag=a.startWith("h");
能否吧一个代码赋给一个变量吗?
在 Java 8 之前,这个是做不到的。但是 Java 8 问世之后,利用 Lambda 特性,就可以做到了。
甚至我们可以让语法变得更简洁。
这样,我们就成功的非常优雅的把“一块代码”赋给了一个变量。而“这块代码”,或者说“这个被赋给一个变量的函数”,就是一个 Lambda 表达式。
但是这里仍然有一个问题,就是变量 hello的类型应该是什么?
在 Java 8 里面,所有的 Lambda 的类型都是一个接口,而 Lambda 表达式本身,也就是”那段代码“,需要是这个接口的实现。这是我认为理解 Lambda 的一个关键所在,简而言之就是,Lambda 表达式本身就是一个接口的实现。直接这样说可能还是有点让人困扰,我们继续看看例子。我们给上面的 hello 加上一个类型:
这种只有一个接口函数需要被实现的接口类型,我们叫它”函数式接口“。为了避免后来的人在这个接口中增加接口函数导致其有多个接口函数需要被实现,变成"非函数接口”,我们可以在这个上面加上一个声明@FunctionalInterface, 这样别人就无法在里面添加新的接口函数了。
最直观的作用就是使得代码变得异常简洁。
虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法。
jdk 8 中有另一个新特性:default, 被 default 修饰的方法会有默认实现,不是必须被实现的方法,所以不影响 Lambda 表达式的使用。
2、Lambda 表达式语法@FunctionalInterface 标记在接口上,“函数式接口”是指仅仅只包含一个抽象方法的接口。
(parameters) -> expression 或 (parameters) ->{ statements; }
语法形式为 () -> {},其中 () 用来描述参数列表,{} 用来描述方法体,-> 为 lambda 运算符 ,读作(goes to)。
// 1. 不需要参数,返回值为 10 () -> 10 // 2. 接收一个参数(数字类型),返回其 5 倍的值 x -> 5 * x // 3. 接受 2 个参数(数字),并返回他们的差值 (x, y) -> x – y // 4. 接收 2 个 int 型整数,返回他们的和 (int x, int y) -> x + y // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回 void) (String s) -> System.out.print(s)3、Lambda 表达式入门案例
注意:此处为6个接口
/** * 无返回值,无参数 */ @FunctionalInterface interface NoReturnNoParam{ void method(); } /** * 无返回值,有一个参数 */ @FunctionalInterface interface NoReturnOneParam{ void method(int a); } /** * 无返回值,有多个参数 */ @FunctionalInterface interface NoReturnMultiParam{ void method(int a,int b); } /** * 有返回值,无参数 */ @FunctionalInterface interface ReturnNoParam{ int method(); } /** * 有返回值,有一个参数 */ @FunctionalInterface interface ReturnOneParam{ int method(int a); } /** * 有返回值,有多个参数 */ @FunctionalInterface interface ReturnMultiParam{ int method(int a,int b); }
注意:下面的代码,其中简化版是指可以省略的写法,两种都是可以的,看个人
public class Test{ public static void main(String[] args) { /** * 无返回值,无参数 */ NoReturnNoParam noReturnNoParam = ()->{ System.out.println("NoReturnNoParam"); }; noReturnNoParam.method(); /** * 无返回值,无参数(简化版) */ NoReturnNoParam noReturnNoParam = ()->System.out.println("NoReturnNoParam"); noReturnNoParam.method(); //------------------------------------- /** * 无返回值,有一个参数 */ NoReturnOneParam noReturnOneParam = (int a)->{ System.out.println("NoReturnOneParam "+a); }; noReturnOneParam.method(10); /** * 无返回值,有一个参数(简化版) */ NoReturnOneParam noReturnOneParam = a ->System.out.println("NoReturnOneParam "+a); noReturnOneParam.method(10); //--------------------------------------- /** * 无返回值,有多个参数 */ NoReturnMultiParam noReturnMultiParam = (int a, int b)->{ System.out.println("NoReturnMultiParam "+a+"\t"+b); }; noReturnMultiParam.method(10,20); /** * 无返回值,有多个参数(简化版) */ NoReturnMultiParam noReturnMultiParam =(a,b)->System.out.println("NoReturnMultiParam "+a+"\t"+b); noReturnMultiParam.method(10,20); //---------------------------------------- /** * 有返回值,无参数 */ ReturnNoParam returnNoParam = ()->{ System.out.print("ReturnNoParam "); return 10; }; System.out.println(returnNoParam.method()); /** * 有返回值,无参数,(简化版) */ ReturnNoParam returnNoParam = ()->10+20; System.out.println(returnNoParam.method()); //-------------------------------------------------- /** * 有返回值,有一个参数 */ ReturnOneParam returnOneParam = (int a)->{ System.out.print("ReturnOneParam "); return a; }; System.out.println(returnOneParam.method(10)); /** * 有返回值,有一个参数(简化版) */ ReturnOneParam returnOneParam = a->a; System.out.println(returnOneParam.method(10)); //-------------------------- /** * 有返回值,有多个参数 */ ReturnMultiParam returnMultiParam = (int a ,int b)->{ System.out.print("ReturnMultiParam "); return a+b; }; System.out.println(returnMultiParam.method(10,20)); /** * 有返回值,有多个参数(简化版) */ ReturnMultiParam returnMultiParam = (a ,b)->a+b; System.out.println(returnMultiParam.method(10,20)); } }4、Lambda 表达式的使用
有时候我们不是必须使用 Lambda 的函数体定义实现,我们可以利用 lambda 表达式指向一个已经被实现的方法。
方法归属者::方法名 静态方法的归属者为类名,普通方法归属者为对象。
/** * 无返回值,无参数 */ @FunctionalInterface interface NoReturnNoParam{ void method(); } /** * 无返回值,有一个参数 */ @FunctionalInterface interface NoReturnOneParam{ void method(int a); } /** * 无返回值,有多个参数 */ @FunctionalInterface interface NoReturnMultiParam{ void method(int a,int b); } /** * 有返回值,无参数 */ @FunctionalInterface interface ReturnNoParam{ int method(); } /** * 有返回值,有一个参数 */ @FunctionalInterface interface ReturnOneParam{ int method(int a); } /** * 有返回值,有多个参数 */ @FunctionalInterface interface ReturnMultiParam{ int method(int a,int b); } public class Test { public static void main(String[] args) { /** * 无返回值,无参数 */ /* NoReturnNoParam noReturnNoParam = ()->{ System.out.println("NoReturnNoParam"); };*/ /** * 简化版 */ NoReturnNoParam noReturnNoParam = ()-> System.out.println("NoReturnNoParam"); noReturnNoParam.method(); /** * 无返回值,有一个参数 */ /* NoReturnOneParam noReturnOneParam = (int a)->{ System.out.println("NoReturnOneParam "+a); };*/ /** * 简化版 */ NoReturnOneParam noReturnOneParam = a -> System.out.println("NoReturnOneParam "+a); noReturnOneParam.method(10); /** * 无返回值,有多个参数 */ /* NoReturnMultiParam noReturnMultiParam = (int a, int b)->{ System.out.println("NoReturnMultiParam "+a+"\t"+b); };*/ NoReturnMultiParam noReturnMultiParam =(a,b)-> System.out.println("NoReturnMultiParam "+a+"\t"+b); noReturnMultiParam.method(10,20); /** * 有返回值,无参数 */ /* ReturnNoParam returnNoParam = ()->{ System.out.print("ReturnNoParam "); return 10; };*/ /** * 简化版 */ ReturnNoParam returnNoParam = ()->10+20; System.out.println(returnNoParam.method()); /** * 有返回值,有一个参数 */ /* ReturnOneParam returnOneParam = (int a)->{ System.out.print("ReturnOneParam "); return a; };*/ /*** * 简化版 */ ReturnOneParam returnOneParam = a->a; System.out.println(returnOneParam.method(10)); /** * 有返回值,有多个参数 */ /*ReturnMultiParam returnMultiParam = (int a ,int b)->{ System.out.print("ReturnMultiParam "); return a+b; };*/ /** * 简化版 */ ReturnMultiParam returnMultiParam = (a ,b)->a+b; System.out.println(returnMultiParam.method(10,20)); } /** * 要求: * 1, 参数的个数以及类型需要与函数接口中的抽象方法一致。 * 2, 返回值类型要与函数接口中的抽象方法的返回值类型一致。 * @param a * @return */ public static int doubleNum(int a){ return 2*a; } public int addTwo(int a){ return a+2; } }
public class Test2 { public static void main(String[] args) { ReturnOneParam returnOneParam = Test::doubleNum; int value = returnOneParam.method(10); System.out.println(value); Test test = new Test(); ReturnOneParam returnOneParam1 = test::addTwo; int value2 = returnOneParam1.method(10); System.out.println(value2); } }
public class Test3 { public static void main(String[] args) { System.out.println(Thread.currentThread().getName()+" 开始"); new Thread(()->{ for(int i=0;i<20;i++){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" "+i); } },"Lambda Thread ").start(); System.out.println(Thread.currentThread().getName()+" 结束"); } }
我们可以调用集合的 public void forEach(Consumer<? super E> action) 方法,通过Lambda 表达式的方式遍历集合中的元素。以下是 Consumer 接口的方法以及遍历集合的操
作。Consumer 接口是 jdk 为我们提供的一个函数式接口。
public class Test4 { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.forEach(System.out::println); } }
我们通过 public boolean removeIf(Predicate<? super E> filter)方法来删除集合中的某个元
素,Predicate 也是 jdk 为我们提供的一个函数式接口,可以简化程序的编写。
public class Test5 { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.removeIf(ele->ele.equals("b")); list.forEach(System.out::println); } }
之前我们若要为集合内的元素排序,就必须调用 sort 方法,传入比较器重写 compare
方法的比较器对象,现在我们还可以使用 lambda 表达式来简化代码。
public class Test6 { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("a"); list.add("d"); list.add("b"); list.add("c"); list.sort((o1,o2)->o1.compareTo(o2)); list.forEach(System.out::println); } }
闭包的本质就是代码片断。所以闭包可以理解成一个代码片断的引用。在 Java 中匿名内部类也是闭包的一种实现方式。
在闭包中访问外部的变量时,外部变量必须是 final 类型,虚拟机会帮我们加上 final 修饰关键字。
public class Test7 { public static void main(String[] args) { int num =10; NoReturnNoParam noReturnNoParam =()->System.out.println(num); noReturnNoParam.method();
1
?
原文:https://blog.51cto.com/u_14962799/2977948