lambda表達(dá)式
一丢氢、什么是lambda表達(dá)式
lambda是接口的一種實(shí)現(xiàn)方式拷淘,是JDK 1.8的新特性
二、怎么使用lambda表達(dá)式
2.1 接口的使用過程
第一步:定義接口
第二步:接口實(shí)現(xiàn)
第三步:接口使用
2.2 lambda實(shí)現(xiàn)接口
接口定義
public interface IMathOperation {
int add(int x,int y);
}//接口的定義
接口的實(shí)現(xiàn)和使用
public class Test {
public static void main(String[] args) {
//接口的實(shí)現(xiàn) 使用lambda表達(dá)式
IMathOperation im = (x,y)->{
return x+y;
};
//接口的使用
System.out.println(im.add(5, 6));
}
}
2.3 lambda表達(dá)式的寫法
語法:(參數(shù))->{方法體}
情況一:只有一個(gè)參數(shù)
public interface IMathOperation {
void add(int x);
}
class Test1{
public static void main(String[] args) {
IMathOperation im = (x) -> {
System.out.println(x);
};
// x ->System.out.println(x);可以省略()以及{},但都不推薦
im.add(5);
}
}
只有一個(gè)參數(shù)時(shí),()可以省略识椰,不推薦省略。
方法實(shí)現(xiàn)只有一行代碼時(shí)深碱,可以省略{}腹鹉,不推薦省略。
情況二:有多個(gè)參數(shù)
public interface IMathOperation {
void add(int x,int y);
}
class Test1{
public static void main(String[] args) {
IMathOperation im = (x,y) -> {
System.out.println(x+y);
};
im.add(5,9);
}
}
情況三:沒有參數(shù)
public interface IMathOperation {
void add();
}
class Test1{
public static void main(String[] args) {
IMathOperation im = () -> {
System.out.println("沒有參數(shù)");
};
im.add();
}
}
在方法實(shí)現(xiàn)中沒有代碼時(shí)敷硅,要寫上{}空方法體
IMathOperation im = () -> { };
im.add();
2.4 lambda表達(dá)式的特征
- 可選的類型聲明:不需要聲明參數(shù)類型功咒,編譯器可以自動(dòng)識(shí)別參數(shù)類型。
- 可選的參數(shù)圓括號(hào):一個(gè)參數(shù)無需使用圓括號(hào)绞蹦,只要不是一個(gè)參數(shù)則需要使用圓括號(hào)力奋。
- 可選的花括號(hào):如果函數(shù)體只有一條語句,則不需要使用花括號(hào)幽七。
2.5 lambda的限制條件
lambda表達(dá)式在實(shí)現(xiàn)接口時(shí)景殷,接口只允許有且只有一個(gè)抽象方法。
這種限制可以使用函數(shù)式接口來定義
三锉走、函數(shù)式接口
3.1 什么是函數(shù)式接口
函數(shù)式接口(@FunctionalInterface):
Lambda表達(dá)式相當(dāng)于對(duì)接口中的方法給出了實(shí)現(xiàn)滨彻,如果在接口中聲明了多個(gè)抽象方法,那么Lambda表達(dá)式實(shí)現(xiàn)的是哪個(gè)方法呢挪蹭?無法確定亭饵,因此要求Lambda表達(dá)式實(shí)現(xiàn)的接口只能有一個(gè)抽象的方法,這樣的接口稱為函數(shù)式接口梁厉。
為了避免接口中出現(xiàn)多個(gè)抽象方法辜羊,可以在接口上使用`@FunctionalInterface`注解,聲明該接口是一個(gè)函數(shù)式接口词顾,例如:
@FunctionalInterface
public interface IMathOperation {
void add();
}
如果在接口中聲明了另外的抽象方法八秃,那么在編譯的時(shí)候,編譯器就會(huì)提示錯(cuò)誤肉盹。
@FunctionalInterface//報(bào)錯(cuò)了昔驱,這個(gè)接口有兩個(gè)抽象方法
public interface IMathOperation {
void add();
void show();//添加一個(gè)抽象方法
}
Multiple non-overriding abstract methods found in interface IMathOperation
3.2 內(nèi)置函數(shù)式接口
內(nèi)置函數(shù)式接口:幫我們定義了接口,我們無需再自己定義接口了
既然Lambda表達(dá)式需要配合函數(shù)式接口來使用上忍,且在函數(shù)式接口中只有一個(gè)抽象方法骤肛,那么完全可以針對(duì)方法的參數(shù)個(gè)數(shù),以及是否有返回值窍蓝,來定義一些常用的函數(shù)式接口腋颠。至于參數(shù)類型和返回值類型,則可以使用泛型來表示吓笙。
其實(shí)我們的Lambda表達(dá)式就是對(duì)函數(shù)式接口的一種簡寫方式淑玫,所以只有是函數(shù)式接口,我們才能用Lambda表達(dá)式;再換句話說絮蒿,Lambda表達(dá)式需要函數(shù)式接口的支持尊搬,那函數(shù)式接口我們可以自己定義,當(dāng)然JDK1.8也給我們提供了一些現(xiàn)成的函數(shù)式接口土涝;
Java 8在java.util.function包中毁嗦,定義了許多函數(shù)式接口回铛,下表列出了四個(gè)基本的函數(shù)式接口。
函數(shù)式接口 | 方法 | 用途 |
---|---|---|
Consumer< T > | void accept(T t) | 消費(fèi)性接口 (有來無回)克锣,即有參數(shù)沒有返回值 |
Predicate< T > | boolean test(T t) | Asset段言型茵肃,有參數(shù),返回值為boolean類型 |
Function< T,R > | R apply(T t) | 函數(shù)型接口袭祟,有參數(shù)有返回值验残,皆為任意類型 |
Supplier | T get() | 供給型接口,無參數(shù)巾乳,有返回值 |
例如
- Consumer< T >
class Test1{
public static void main(String[] args) {
Consumer<String> im = (s) -> {
System.out.println(s);
};
im.accept("Consumer");
}
}
- Predicate< T >
class Test1{
public static void main(String[] args) {
Predicate<String> im = (s) -> {
if (s.equals("芝麻開門")){
System.out.println("密碼正確");
return true;
}else {
return false;
}
};
im.test("芝麻開門");
}
}
- Function< T,R >
class Test1{
public static void main(String[] args) {
Function<Integer,String> im = (x) -> {
return x>0?"正確":"錯(cuò)誤";
};
System.out.println(im.apply(10));
}
}
- Supplier
class Test1{
public static void main(String[] args) {
Supplier im = () -> {
return "很久很久以前您没,巨龍突然出現(xiàn)";
};
System.out.println(im.get());
}
}
四、方法引用
方法引用:幫我們完成了接口實(shí)現(xiàn)胆绊,省去了我們自己定義Lambda表達(dá)式
如果一個(gè)類中的實(shí)現(xiàn)方法氨鹏,其參數(shù)列表和返回值類型與某個(gè)函數(shù)式接口中的方法一致,那么可以使用方法引用的方式來代替Lambda表達(dá)式压状。Java編譯器會(huì)利用函數(shù)式接口中方法的參數(shù)來調(diào)用引用的方法仆抵,并將該方法的返回值(如果有的話)作為接口方法的返回值。
方法引用使用操作符“::”將對(duì)象或者類的名字與方法名分隔開。主要有以下三種形式:
● 對(duì)象::實(shí)例方法名
● 類名::靜態(tài)方法名
● 對(duì)象::靜態(tài)方法名
class Test1{
public static String getStr1(String str1){
return str1;
}
public String getStr2(String str2){
return str2;
}
public static void main(String[] args) {
Function<String,String> fun = (str) -> {
return "很久很久以前\n巨龍突然出現(xiàn)\n"+str;
};
System.out.println(fun.apply("帶來災(zāi)難\n" +"帶走了公主又消失不見"));
//類名::靜態(tài)方法名
Function<String,String> fun1 = Test1::getStr1;
System.out.println(fun1.apply("很久很久以前\n巨龍突然出現(xiàn)\n"));
//對(duì)象::實(shí)例方法名
Test1 test = new Test1();
Function<String,String> fun2 = test::getStr2;
System.out.println(fun2.apply("帶來災(zāi)難\n" + "帶走了公主又消失不見"));
}
}