1. Java函數(shù)式接口
Java實(shí)現(xiàn)函數(shù)式編程的方式是函數(shù)式接口(functional interface),函數(shù)式接口簡(jiǎn)單來說决乎,是只包含一個(gè)抽象方法的接口。比如Java標(biāo)準(zhǔn)庫中的java.lang.Runnable和 java.util.Comparator都是典型的函數(shù)式接口。
java 8提供 @FunctionalInterface作為函數(shù)式接口的注解,該注解非強(qiáng)制使用嬉探,主要防止團(tuán)隊(duì)的其他人員錯(cuò)誤地往接口中添加新的方法。
2. lambda表達(dá)式
lambda表達(dá)式是匿名方法棉圈,是函數(shù)式接口的匿名實(shí)現(xiàn)涩堤。
使用lambda表達(dá)式實(shí)現(xiàn)Runnable例子:
// 使用匿名內(nèi)部類
new Thread(new Runnable() {
public void run() {
System.out.println("Hello world !");
}
}).start();
// 使用 lambda 表達(dá)式
new Thread(() -> System.out.println("Hello world !")).start();
3. lambda語法
(parameters) -> expression
或者
(parameters) -> { statements; }
JButton jb=new JButton();
jb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("press button");
}
});
jb.addActionListener((ActionEvent e)->{System.out.println("press button");});
jb.addActionListener((e)->{System.out.println("press button");});
jb.addActionListener((x)->System.out.println("press button"));
jb.addActionListener(x->System.out.println("press button"));
為了更好的支持lambda,Java8引入了一個(gè)新包java.util.function分瘾,它里面包含了常用的函數(shù)式接口胎围,例如:
Predicate<T>——接收T對(duì)象并返回boolean
Consumer<T>——接收T對(duì)象,不返回值
Function<T, R>——接收T對(duì)象芹敌,返回R對(duì)象
Supplier<T>——提供T對(duì)象(例如工廠)痊远,不接收值
UnaryOperator<T>——接收T對(duì)象垮抗,返回T對(duì)象
BinaryOperator<T>——接收兩個(gè)T對(duì)象氏捞,返回T對(duì)象
在參數(shù)為這些接口的地方,我們就可以直接使用lambda表達(dá)式了冒版!
4. 方法引用(Method references)
lambda表達(dá)式允許我們定義一個(gè)匿名方法液茎,并允許我們以函數(shù)式接口的方式使用它。我們也希望能夠在已有的方法上實(shí)現(xiàn)同樣的特性辞嗡。
方法引用和lambda表達(dá)式擁有相同的特性(例如捆等,它們都需要一個(gè)目標(biāo)類型,并需要被轉(zhuǎn)化為函數(shù)式接口的實(shí)例)续室,不過我們并不需要為方法引用提供方法體栋烤,我們可以直接通過方法名稱引用已有方法。
以下面的代碼為例挺狰,假設(shè)我們要按照name為Person數(shù)組進(jìn)行排序:
class Person {
private final String name;
private final int age;
public int getAge() { return age; }
public String getName() {return name; }
...
}
Person[] people = ...
Comparator<Person> byName = Comparator.comparing(p -> p.getName());
Arrays.sort(people, byName);
在這里我們可以用方法引用代替lambda表達(dá)式:
Comparator<Person> byName = Comparator.comparing(Person::getName);
方法引用的形式
方法引用的標(biāo)準(zhǔn)形式是:類名::方法名明郭。(注意:只需要寫方法名,不需要寫括號(hào))
有以下四種形式的方法引用:
引用靜態(tài)方法
引用某個(gè)對(duì)象的實(shí)例方法
引用某個(gè)類型的任意對(duì)象的實(shí)例方法
引用構(gòu)造方法
-
引用靜態(tài)方法
ContainingClass::staticMethodName
例子: String::valueOf丰泊,對(duì)應(yīng)的Lambda:(s) -> String.valueOf(s)
比較容易理解薯定,和靜態(tài)方法調(diào)用相比,只是把.換為:: -
引用特定對(duì)象的實(shí)例方法
containingObject::instanceMethodName
例子: x::toString瞳购,對(duì)應(yīng)的Lambda:() -> this.toString()
與引用靜態(tài)方法相比话侄,都換為實(shí)例的而已 -
引用特定類型的任意對(duì)象的實(shí)例方法
ContainingType::methodName
例子: String::toString,對(duì)應(yīng)的Lambda:(s) -> s.toString()
實(shí)例方法要通過對(duì)象來調(diào)用,方法引用對(duì)應(yīng)Lambda年堆,Lambda的第一個(gè)參數(shù)會(huì)成為調(diào)用實(shí)例方法的對(duì)象吞杭。 -
引用構(gòu)造函數(shù)
ClassName::new
例子: String::new,對(duì)應(yīng)的Lambda:() -> new String()
構(gòu)造函數(shù)本質(zhì)上是靜態(tài)方法嘀韧,只是方法名字比較特殊篇亭。
寫個(gè)例子幫本節(jié)內(nèi)容串一下幫助理解:
class Person {
Integer age;
public static int compareByAge(Person a,Person b){return a.age.compareTo(b.age);}
public int compareByAge2(Person b){return age.compareTo(b.age);}
public static int compareBy18(Person p){return p.age.compareTo(18);}
public int compareBy14(){return age.compareTo(14);}
}
public void sort(){
Person [] persons=new Person[10];
//使用匿名類
Arrays.sort(persons, new Comparator<Person>() {
public int compare(Person o1, Person o2) {
return o1.age.compareTo(o2.age);
}
});
//使用lambda表達(dá)式
Arrays.sort(persons, (o1, o2) -> o1.age.compareTo(o2.age));
//使用lambda表達(dá)式和類的靜態(tài)方法
Arrays.sort(persons, (o1, o2) -> Person.compareByAge(o1,o2));
//使用lambda表達(dá)式和實(shí)例方法
Arrays.sort(persons, (o1, o2) -> o1.compareByAge2(o2));
//使用方法引用
//引用的是類的靜態(tài)方法
Arrays.sort(persons, Person::compareByAge);
//引用特定類型的任意對(duì)象的實(shí)例方法
Arrays.sort(persons, Person::compareByAge2);
//引用的是類的靜態(tài)方法
Arrays.sort(persons,Comparator.comparing(Person::compareBy18));
//引用特定類型的任意對(duì)象的實(shí)例方法
Arrays.sort(persons,Comparator.comparing(Person::compareBy14));
}
`