什么是 Lambda 表达式?java
为何使用 Lambda ?算法
简洁实现接口对接;闭包
虽然可使用 Lambda 表达式对某些接口进行实现,可是并非全部的接口均可以使用 Lambda 来实现;ide
实现要求:要实现的抽象方法只能是一个;函数
在 Java 8 中对接口实现了一个新特性
default
,被此方法修饰的方法在类中有一个默认实现,因此不影响使用 Lambda 的实现;优化
@FunctionalInterface:this
一个用来修饰函数式接口的,接口中的抽象方法只能有一个;.net
// 错误代码展现 @FunctionalInterface interface Comparer{ int compare(int a,int b);// 方法一 int show(int a,int b); // 方法二 }
↑ ↑ ↑ 错误代码展现 ↑ ↑ ↑线程
什么是函数式接口?code
代码示例
public class DEMO{ public static void main(String[] args){ // 方法一:使用接口实现类 Comparator comparator = new MyComparator(); //方法二:使用匿名内部类 Comparator comparator = new Comparator(){ @Override public int compare(int a,int b){ return a-b; } } //方法三:使用Lambda表达式 Comparator comparator2 = (a,b) -> a-b; } } // 一个接口 interface Comparator{ int compare(int a,int b); } //方法一:使用实现类实现接口 class MyComparator implements Comparator{ @Override public int compare(int a,int b){ return a-b; } }
基础语法:
元素:
()
:用来描述参数列表{}
:用来描述方法体->
:分隔 Lambda 运算法,读做:goes to
几种状况:
一、无参 无返回
// 无参 无返回 LambdaTest lam1 = ()->{ Sout("Hello World!"); } lam1.test(); // 结果:输出`Hello World!`二、单个参 无返回
// 无参 单个返回值 LambdaTest lam2 = (int a)->{ Sout(a); } lam2.test(10); // 结果:输出`10`三、多个参 无返回
LambdaTest lam3 = (int a,int b)->{ Sout(a+b); } lam3.test(10,11); // 结果:输出`21`四、无参 有返回
LambdaTest lam4 = ()->{ Sout(100); return 100; } int ret = lam4.test(); // 结果:输出`100` ; 返回 `100`五、有参数 有返回
LambdaTest lam5 = (int a)->{ Sout(a*2); return a*2; } int ret = lam5.test(10); // 结果:输出`20` ; 返回 `20`
↑ ↑ ↑ 要注意 必定要定义相应的 函数式接口
↑ ↑ ↑
interface Lamx{ int test(int a,int b); } Lamx lamx = (int a,int b)->{ Sout("a=" + a + "\nb=" + b); // return a+b; }
上面报错了?Lambda表达式如何知道有返回值?
Lambda 由于定义的接口有了说明,好比接口中写
int test(int a);
第一个int
表示返回值类型,第二个int
表示参数类型,因此 舍去了return
就会报错;
既然在定义接口的时候已经定义了类型,那么是否是能够在写入参数的时候,将参数的类型描述给省略掉呢?
精简1:省略参数描述int
代码演示:
interface Lamx{ int test(int a,int b); } Lamx lamx = (a,b)->{ Sout("a=" + a + "\nb=" + b); return a+b; }
接口中已经说明了有int
类型的返回值,因此不写return
是错误的;
两个必须同时省略,不能一个写一个不写;
精简2:省略小括号()
代码演示:
interface Lamx{ int test(int a); } Lamx lamx = a -> { Sout("a=" + a ); return a; }
当 入参 只有一个的时候,能够省略入参的 括号;
{}
interface Lamx{ int test(int a); } Lamx lamx = a -> Sout( a );
当 函数 只有一行的时候,能够省略大括号;
return
interface Lamx{ int test(int a); } Lamx lamx = a -> a;
若是惟一一条语句是return
语句,那么省略大括号的同时,也必须省略return
;
Lamx lamx = (a,b)->a+b; lamx.test(5,10);
public class Test{ public static void main(String[] args){ // 实现方式一: 传统 Lambda 语法 Lamx lamx = a -> change(a); // 实现方式二: 双" : "语法 Lamx lamx = Test::change; } public static int change(int a){ return a*2; } }
将 Lambda 指向一个已经实现的方法;语法规则 -- 方法隶属者::方法名
此处的change
是一个静态方法,隶属者就是Test
类,因此就是Test::change
// 构造方法 public class Person{ public String name; public int age; public Person(){ Sout("Person类的 无参 构造方法执行了;"); } public Person(String name,int age){ this.name = name; this.age = age; Sout("Person类的 有参 构造方法执行了;"); } }
// Lambda 语法 public class Lamx{ public static void main(String[] args){ // 原始方法 PersonCreater creater1 = () -> { return new Person(); }; // 简化方法 PersonCreater creater2 = () -> new Person(); // 构造方法的引用 PersonCreater creater3 = Person::new; Person a = creater3.getPersonNull(); Person a = creater3.getPersonDouble("张三",18); } } //接口中要说明 返回值类型 方法参数!!! interface PersonCreater{ Person gerPersonNull(); Person getPersonDouble(String name,int age); }
实现语法 -- 类::new
一、已知在一个 ArrayList 类中有若干个 Person 对象,讲这些Person对象按照年龄进行降序排序;
public class Exercise{ public static void main(String[] args){ ArrayList<Person> list = new ArrayList<>(); list.add(new Person("张三",12)); list.add(new Person("李四",13)); list.add(new Person("韩梅梅",16)); list.add(new Person("赵四",6)); list.add(new Person("尼古拉斯凯奇",46)); list.add(new Person("Tony",54)); list.sort((o1,o2)-> o2.age-o1.age); } }
二、使用TreeSet排序
TreeSer<Person> set = new TreeSer<>((o1,o2)->o2.age-01.age); set.add(new Person("xiaoming",10)); set.add(new Person("wanggang",11)); set.add(new Person("zhaosi",8)); set.add(new Person("Nigu",43)); set.add(new Person("Tony",22)); set.add(new Person("poily",8)); set.add(new Person("Wngffei",40)); Sout(set); //运行结果:基本正确,可是只有一个8岁的人;
代码优化
TreeSer<Person> set = new TreeSer<>((o1,o2)->{ if(o1.age >= o2.age){ retrun -1; }else{ return 1; } }); set.add(new Person("xiaoming",10)); set.add(new Person("wanggang",11)); set.add(new Person("zhaosi",8)); set.add(new Person("Nigu",43)); set.add(new Person("Tony",22)); set.add(new Person("poily",8)); set.add(new Person("Wngffei",40)); Sout(set); //运行结果:正确;
public static void main(String[] args){ ArrayList<Interger> list -= new ArrayList<>(); Collection.addAll(list,1,2,3,4,5,6,7,8,9,0); list.forEach(ele->{ if(ele%2 == 0) Sout(ele); }); }
实现线程的实例化;
public static void main(String[] args){ Thread t = new Thread(()->{ for(int i=0;i<100;i++){ Sout(i); } }); t.start(); }
public static void (String[] args){、 //最经常使用的是Predicate、Consumer、Function、Supplier // Predicate<T> : 参数T ·返回值 boolean // IntPredicate : int-> boolean // LongPredicate : long->boolean // DoublePredicate : double // Consumer<T> : 参数T ·返回值 void // IntConsumer : int ->void // LongConsumer // DoubleConsumer // Function<T,R> : 参数T ·返回值 R // IntFuncation : int->R // LongFunction // DoubleFunction // IntToLongFunction: int->long // IntToDoubleFunction // LongToIntFunction // LongToDoubleFunction // DoubleToIntFunction // DoubleToLongFunction // Supplier<T> : 参数无 ·返回值 T // ……省略好多好多 // UnaryOperator<T> : 参数T ·返回值T // BinaryOperator : 参数T,T ·返回值T // BiFunction<T,U,R>: 参数T,U ·返回值R // BiPredicate<T,U> : 参数T,U ·返回值boolean // BiConsumer<T,U> : 参数T,U ·返回值void }
闭包
?
public static void main(String[] args){ int n = getNum().get(); Sout(n); //结果是10; } private static Supplier<Integer> getNum(){ int num = 10; return ()->{ return num; }; }
代码二:
PSVM(String[] args){//public static void main int a = 10; Consumer<Integer> c = ele->{ Sout(a+1); }; c.accept(1);// 结果11 Consumer<Integer> c = ele->{ Sout(a++); }; c.accept();// 结果报错,由于 闭包 中的变量必须是 final 的(也就是一个常量),因此不能修改这个值 }