目录
3、lambda表达式
为什么引入lambda表达式
lambda表达式是一个可传递的代码块,可以在以后执行一次或多次。
之前讲的定时输出语句和按长度进行数组排序示例有一个共同点就是:代码块传递到某个对象(定时器或sort方法),并在将来某个时间调用。
到目前为止,Java要传递代码块并不容易,不能直接传递代码段。Java是一种面向对象语言,所以必须构在一个对象,且这个对象的类需要一个方法包含所需要的代码。
lambda表达式的语法
以按长度排序为例子。我们比较字符串长度,需要计算:first.length() - second.length();first和second是字符串,Java是强类型语言,所以我们还要指定他们的类型:
(String first, String second) -> first.length() - second.length();
lambda表达式就是一个代码块,以及必须传入代码的变量规范。
lambda的一般形式:(参数)-> { 表达式 }
1、即使没有参数,也需要空括号,像无参数方法一样。
2、如果参数类型可以推导出来,可以忽略其类型,如:
Comparator<String> cmp = {first, second) -> first.length() - second.length();
//因为范型声明为String,一个lambda表达式赋值给一个字符串比较器对象,所以编译器可以推导出两参数为String对象
3、如果仅有一个参数,且类型可推导,还能省略括号。
ActionListener listener = event -> {
System.out.println("The time is:" + new Date());
};
4、无需声明返回类型,会根据上下文推导。
5、若一个lambda 表达式只在某些分支返回一个值,另外一些分支不返回值,这是不合法的。如
(int x) -> {
if(x > 0)
return 1;
};
//不合法
lambda使用示例:
1、按字符串长度排序:源代码
package com.company;
import java.util.Arrays;
import java.util.Comparator;
/**
* This program demonstrates the use of the Comparator interface
*/
public class Main {
public static void main(String[] args) {
String[] friends = {"Amy","Peter","John","Tifany","Jonathan"};
Arrays.sort(friends, new LengthComparator());
for(String s : friends){
System.out.println(s);
}
}
}
class LengthComparator implements Comparator<String>{
@Override
public int compare(String first,String second){
return first.length() - second.length();
}
}
使用lambda表达式:
package com.company;
import java.util.Arrays;
import java.util.Comparator;
/**
* This program demonstrates the use of the Comparator interface
*/
public class Main {
public static void main(String[] args) {
String[] friends = {"Amy","Peter","John","Tifany","Jonathan"};
Arrays.sort(friends,(String first,String second) -> second.length() - first.length());
for(String s : friends){
System.out.println(s);
}
}
}
2、定时输出语句:源代码
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
//消除了javax.swing.Timer与javax.util.TImer之间的二义性。
public class TimerTest{
public static void main(String[] args){
ActionListener listener = new TimePrinter();
//construct a timer that calls the listener
//once every 5 seconds
Timer t = new Timer(5000, listener); //Timer构造器有两个参数,第一个是时间间隔,第二个是监听器对象
t.start(); //启动定时器
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit();
}
}
class TimePrinter implements ActionListener{
@Override
public void actionPerformed(ActionEvent event){
System.out.println("The time is: " + new Date());
Toolkit.getDefaultToolkit().beep();
}
}
使用lambda 表达式:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
//消除了javax.swing.Timer与javax.util.TImer之间的二义性。
public class TimerTest{
public static void main(String[] args){
ActionListener listener = new TimePrinter();
//construct a timer that calls the listener
//once every 5 seconds
Timer t = new Timer(5000, event -> {
System.out.println("The time is: " + new Date());
Toolkit.getDefaultToolkit().beep();
});
t.start(); //启动定时器
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit();
}
}
函数式接口
Java中有很多封装代码块的接口,如ActionListener或Comparator。lambda表达式与这些接口是兼容的。
对于只有一个抽象方法的接口,需要这种接口对象时,就可以提供一个lambda 表达式。这种接口称为函数式接口(functional interface)。
为什么要求函数式接口必须有一个抽象方法&#x