lambda
函数式接口
当一个接口定义且仅定义了一个方法时,被称作函数式接口,我们可以用@FunctionalInterface注解来约束一个接口为函数式接口:
@FunctionalInterface interface FunctionalInterface{ int i=12; void IsOpen(); }
使用lambda表达式定义接口对象
在实例化一个接口对象的时候,可以利用lamba表达式直接定义接口对象和对应的实现,lambda可以用在变量声明、方法定义中,格式为:
(参数列表) -> action
其中的action可以为一段代码块(方法实体),一个变量(作为方法的返回值),一行代码(针对void)。例如可以用来很方便的创建一个匿名内部类,创建一个新线程:
new Thread( () -> System.out.print("hello") ).start();
单一的变量可以将参数列表的括号去掉(不建议这样做),参数列表可以有也可以没有类型声明,下面是一个lambda的例子:
public class LambdaTest { @FunctionalInterface interface LambdaFun1{ //接口1 String s=""; void get(int a); } @FunctionalInterface interface LambdaFun2{ //接口2 int get(int a,int b); } public static void main(String args[]){ LambdaFun1 t1 = a -> System.out.print(a+1);//注意a是形参,形参不能与变量名冲突 LambdaFun2 t2 = (c,d) -> c+d; } }
lambda表达式多用于函数式接口中,但也复写那些参数列表唯一的方法生成对象
方法引用
是在某种程度上对已实现方法的lambda表达式的一种优化,格式为 ::,两冒号前为数据类型,可以是类或是既有的对象,冒号后是执行的方法,一个典型的应用就是集合类的compare,我们写了一个类并且定义了compare方法,为了更高的自由度我们并没有选择继承Comparable接口的方式:
class Person{ int age; String name; Person(int age,String name){ this.age=age; this.name=name; } @Override public String toString() { return age+" "; } public static int compareTo(Person a,Person b) { return a.age-b.age; //递增排列。用于方法引用,实现了倒序排列使用静态免去了实例化 } }
我们知道若想排序需要在sort的第二个参数定义一个函数式接口Comparator对象并重写它的compare方法,对于既有的方法,可以依赖方法引用实现:
public static void main(String args[]){ Arrays.sort(pArr,(a,b) ->a.age-b.age); // for(int i=0;i<pArr.length;i++){ System.out.print(pArr[i]); } List<Person> pArr = new ArrayList<>(); pArr.add(new Person(12,"Cosl")); pArr.add(new Person(15, "Jack")); pArr.add(new Person(13, "sherk")); pArr.forEach(System.out::print); //foreach也是一种应用 Collections.sort(pArr,Person::compareTo); //用方法引用实现 Collections.sort(pArr,(a,b) -> a.age-b.age); //直接写lambda Collections.sort(pArr,(a,b) -> Person.compareTo(a,b)); //引用静态方法的lambda Collections.sort(pArr, new Comparator<Person>() { //直接使用 @Override public int compare(Person a, Person b) { return a.age-b.age; } } pArr.forEach(System.out::print); }
输出:12 15 13 12 13 15