没有用Lambda表达式的写法:
Comparator<Transaction> byYear = new Comparator<Transaction>() { @Override public int compare(Transaction o1, Transaction o2) { return o1.getValue().compareTo(o2.getValue()); } };
Lambda表达式的写法:
Comparator<Transaction> byYear = (o1, o2) -> o1.getValue().compareTo(o2.getValue());
Lambda表达式的三部分:
-
参数列表 这里采用了Comparator中compare的方法的参数,两个Transaction
-
箭头 箭头->把参数列表和Lambda主体分隔开.
-
Lambda主体 比较两个Transaction的年份,表达式就是Lambda的返回值
下面提供了一些Lambda的例子和使用案例
(List<String> list) -> list.isEmpty(); () -> new Transaction(); (Transaction t) -> { System.out.println("Year = " + t.getYear()); } (String s) -> s.length(); (int a, int b) -> a * b;
在哪里使用Lambda接口
可以在函数式接口上使用Lambda表达式,
-
函数式接口 就是只定义了一个抽象方法的接口,继承的也不行 作用: 是函数式接口一个具体的实现实例
例子:
Runnable r2 = new Runnable() {//使用匿名类 @Override public void run() { System.out.println("hello world 2"); } }; process(r1);//打印hello world 1 process(r2);//打印hello world 2 process(()-> System.out.println("hello world 3"));//利用直接传递Lambda表达式作为实现实例 打印hello world 3
如果我们去看看新的java Api,会发现函数式接口带有@FunctionalInterface标注,这个标注表示该接口被设计成一个函数式接口,如果你用了该注解,而它不是却不是函数式接口,编译器会返回一个提示错误.
/** * The <code>Runnable</code> interface should be implemented by any * class whose instances are intended to be executed by a thread. The * class must define a method of no arguments called <code>run</code>. * <p> * This interface is designed to provide a common protocol for objects that * wish to execute code while they are active. For example, * <code>Runnable</code> is implemented by class <code>Thread</code>. * Being active simply means that a thread has been started and has not * yet been stopped. * <p> * In addition, <code>Runnable</code> provides the means for a class to be * active while not subclassing <code>Thread</code>. A class that implements * <code>Runnable</code> can run without subclassing <code>Thread</code> * by instantiating a <code>Thread</code> instance and passing itself in * as the target. In most cases, the <code>Runnable</code> interface should * be used if you are only planning to override the <code>run()</code> * method and no other <code>Thread</code> methods. * This is important because classes should not be subclassed * unless the programmer intends on modifying or enhancing the fundamental * behavior of the class. * * @author Arthur van Hoff * @see java.lang.Thread * @see java.util.concurrent.Callable * @since JDK1.0 */@FunctionalInterfacepublic interface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run(); }
方法引用
方法引用让你可以重复使用现有的方法定义,并像Lambda一样传递他们.例如下面排序的例子:
List<Apple> inventory = new ArrayList<>(); inventory.sort(Comparator.comparing(Apple::getWeight)//按重量排序 .reversed()//递减 倒序 .thenComparing(Apple::getCountry));//如果重量一样 按国家排序
当你需要使用方法引用时,目标引用放在分隔符::前,方法名称放在后面,例如Apple::getWeight 就是引用了Apple类中定义的getWeight,请记住,不需要括号,因为你没有实际调用这个方法.
方法引用主要有三类:
-
指向静态方法的方法引用(例如Integer的parseInt方法 写作Integer::parseInt) .
-
指向任意类型实例方法的方法引用(例如String的length方法,写作String::length)
-
指向现有对象的实例方法的方法引用(假设你有一个局部变量expensive用于存放Transaction类型的对象,他支持实例方法getValue,那么你就可以写expensive::getValue).
构造函数引用
对于一个现有构造函数,你可以利用它的名称和关键字new 来创建他的一个引用:ClassName::new,它的功能与指向静态方法的引用类型类似.