Java 8 新特性(一)lambda表達(dá)式

Java 9 好像也快出了圾浅,不過我連Java 8的新特性都還沒認(rèn)真研究過疆股,所以這幾篇文章就是來介紹Java 8的新特性的锅必。首先盼樟,第一個重要的特性就是傳說中的lambda表達(dá)式了氢卡,雖然初學(xué)可能覺得這東西很難理解,但是一旦學(xué)會了晨缴,你就會發(fā)現(xiàn)離不開它了译秦。

在現(xiàn)代編程語言中,lambda表達(dá)式這個語言特性已經(jīng)成為了標(biāo)配氯檐。當(dāng)然不同語言中的lambda表達(dá)式概念和實(shí)現(xiàn)形式可能會稍有差別慨亲。不過不管在哪種語言中鹰椒,我們都可以把lambda表達(dá)式簡單的理解為匿名函數(shù)。在Java中阁吝,lambda表達(dá)式和只有一個方法的接口是差不多的,所以這樣的接口又叫做SAM接口(Single Abstract Method interfaces)械拍。

初識lambda表達(dá)式

說了半天突勇,下面先來看看實(shí)際例子吧装盯。我們在編寫多線程代碼的時候,常常需要編寫實(shí)現(xiàn)Runnable的類甲馋。有時候?yàn)榱耸∈鹿∧危覀儠懗赡涿麅?nèi)部類的形式。

Runnable task1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("任務(wù)一");
    }
};

匿名內(nèi)部類不好理解定躏,而且寫起來也非常丑陋账磺。由于Runnable接口內(nèi)只有一個方法,所以它是一個SAM接口痊远,我們可以用lambda表達(dá)式改寫它垮抗。那么改寫之后是什么樣子的呢?不要驚訝拗引,只需要一行代碼借宵。

Runnable task2 = () -> System.out.println("任務(wù)二");

因此,我們可以看到lambda表達(dá)式的簡潔之處矾削。下面就來詳細(xì)介紹一下lambda表達(dá)式的形式壤玫。

lambda表達(dá)式形式

lambda表達(dá)式可以用在需要SAM接口對象的地方,由于編譯器這時候知道所需要的接口和對應(yīng)方法的簽名哼凯。所以lambda表達(dá)式的類型聲明可以省略欲间,具體類型由編譯器自行推斷。lambda表達(dá)式的基本形式如下断部。

(參數(shù)列表) -> {方法體}

為了方便說明猎贴,我這里定義了一組接口,用于之后的lambda表達(dá)式實(shí)現(xiàn)蝴光。

@FunctionalInterface
interface Interface1 {
    void f();
}


@FunctionalInterface
interface Interface2 {
    void f(int a);
}

@FunctionalInterface
interface Interface3 {
    void f(int a, int b);
}

@FunctionalInterface
interface Interface4 {
    int f(int a, int b);
}

無參lambda

先來看看無參數(shù)的lambda表達(dá)式她渴。特別地,如果方法體只有一行代碼蔑祟,可以省略方法體的大括號趁耗。

Interface1 interface1 = new Interface1() {
    @Override
    public void f() {
        System.out.println("f");
    }
};
Interface1 lambda1 = () -> {
    System.out.println("f");
};
//如果方法體只有一行代碼,可以省略大括號
Interface1 lambda1a = () -> System.out.println("f");

多個參數(shù)的lambda

我們可以看到由于編譯器可以進(jìn)行類型推斷疆虚,所以lambda表達(dá)式的參數(shù)列表不需要參數(shù)類型聲明苛败,而且由于我只有一行代碼,所以大括號也省略了径簿。

//多個參數(shù)lambda
Interface3 interface3 = new Interface3() {
    @Override
    public void f(int a, int b) {
        System.out.println(a + b);
    }
};
Interface3 lambda3 = (a, b) -> System.out.println(a + b);

帶返回值的lambda

帶返回值的lambda表達(dá)式其實(shí)和普通的一樣罢屈,只不過需要在方法體的最后使用return語句。值得注意的是最后一個例子篇亭,如果方法體本身足夠簡單缠捌,可以直接將返回值表達(dá)式寫在lambda表達(dá)式的右邊,編譯器也會正確對待這種情況译蒂。

//帶有返回值的lambda
Interface4 interface4 = new Interface4() {
    @Override
    public int f(int a, int b) {
        return a + b;
    }
};
Interface4 lambda4 = (a, b) -> {
    return a + b;
};
Interface4 lambda4a = (a, b) -> a + b;

單個參數(shù)的lambda

如果lambda表達(dá)式只有一個參數(shù)曼月,那么參數(shù)列表的小括號也可以省略肃叶,例如下面的第二個例子。下面第三個例子演示了另一個新語法方法引用十嘿,如果lambda表達(dá)式的形式是單個參數(shù)a -> 某個只有一個參數(shù)的方法(a)因惭,那么就可以簡寫成方法引用的形式類::方法。方法引用是一個新語法绩衷,如果見到了不要奇怪蹦魔,這也是正確的Java代碼。

//一個參數(shù)的lambda
Interface2 interface2 = new Interface2() {
    @Override
    public void f(int a) {
        System.out.println(a);
    }
};
Interface2 lambda2 = (a) -> System.out.println(a);
Interface2 lambda2a = a -> System.out.println(a);
Interface2 methodReference = System.out::println;

函數(shù)接口

@FunctionalInterface注解

如果查看JDK源碼的一些接口咳燕,會發(fā)現(xiàn)它們上面添加了@FunctionalInterface注解勿决。例如上面提到的Runnable接口。

@FunctionalInterface
public interface Runnable {

    public abstract void run();
}

這個注解用于標(biāo)注函數(shù)接口招盲,也就是上面提到的SAM接口低缩。如果一個接口中包含了不止一個方法,那么函數(shù)接口注解就會觸發(fā)編譯錯誤曹货。這個功能類似于@Override注解咆繁。當(dāng)然并不是說要使用lambda表達(dá)式必須標(biāo)記這個注解,只要接口中只有一個方法顶籽,那么就可以使用lambda表達(dá)式玩般。

其實(shí)函數(shù)接口可以包括不止一個方法,除了一個普通的抽象方法之外礼饱,函數(shù)接口還可以包含一個在java.lang.Object類中聲明的方法坏为。Java 8新增了默認(rèn)方法特性,如果接口的實(shí)現(xiàn)類沒有實(shí)現(xiàn)java.lang.Object類中的這些基本方法镊绪,那么就會調(diào)用java.lang.Object類中的實(shí)現(xiàn)作為默認(rèn)實(shí)現(xiàn)匀伏。

@FunctionalInterface
interface Interface5 {
    void f();

    String toString();
}

預(yù)定義的函數(shù)接口

java.util.function包下定義了大量預(yù)定義的函數(shù)接口,它們包含了各種各樣的形式蝴韭,基本涵蓋了編程的各個方面够颠。同學(xué)們最好對這些函數(shù)接口的形式稍作了解,以后碰到的時候就不會一頭霧水了万皿。

函數(shù)接口

lambda表達(dá)式應(yīng)用

編寫線程

前面提到了摧找,可以使用lambda表達(dá)式簡化線程代碼的編寫核行,不再需要冗長的匿名內(nèi)部類牢硅。

//編寫線程
Runnable task = () -> System.out.println("簡單的任務(wù)");
Executor executor = Executors.newCachedThreadPool();
executor.execute(task);

編寫比較器

比方說我們有一個學(xué)生類,有姓名和年齡兩個字段芝雪。如果需要按照某種規(guī)則來進(jìn)行排序减余,可以使用比較器Comparator接口來比較,利用lambda表達(dá)式同樣可以簡化這部分代碼的編寫惩系。

class Student {
    private String name;
    private int age;
    //其余方法已省略
}

可以看到比較規(guī)則只需要一條lambda表達(dá)式即可傳入位岔,非常方便如筛。后面兩個例子是Comparator接口新增的工具方法,可以幫助我們簡化比較代碼的編寫抒抬,這里使用了方法引用來簡化代碼杨刨。comparing等方法的返回值仍然是Comparator,所以可以鏈?zhǔn)秸{(diào)用進(jìn)行多級比較擦剑。

List<Student> students = new ArrayList<>();
students.add(new Student("yitian", 25));
students.add(new Student("anna", 26));
students.add(new Student("wang5", 24));

students.sort((a, b) -> a.getAge() - b.getAge());
System.out.println(students);

students.sort(Comparator.comparing(Student::getName));
System.out.println(students);

students.sort(
        Comparator.comparing(Student::getName)
                .thenComparing(Student::getAge));
System.out.println(students);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末妖胀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子惠勒,更是在濱河造成了極大的恐慌赚抡,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纠屋,死亡現(xiàn)場離奇詭異涂臣,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)售担,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門赁遗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人族铆,你說我怎么就攤上這事吼和。” “怎么了骑素?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵炫乓,是天一觀的道長。 經(jīng)常有香客問我献丑,道長末捣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任创橄,我火速辦了婚禮箩做,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘妥畏。我一直安慰自己邦邦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布醉蚁。 她就那樣靜靜地躺著燃辖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪网棍。 梳的紋絲不亂的頭發(fā)上黔龟,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼氏身。 笑死巍棱,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛋欣。 我是一名探鬼主播航徙,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼陷虎!你這毒婦竟也來了捉偏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤泻红,失蹤者是張志新(化名)和其女友劉穎夭禽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谊路,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡讹躯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了缠劝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片潮梯。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖惨恭,靈堂內(nèi)的尸體忽然破棺而出秉馏,到底是詐尸還是另有隱情,我是刑警寧澤脱羡,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布萝究,位于F島的核電站,受9級特大地震影響锉罐,放射性物質(zhì)發(fā)生泄漏帆竹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一脓规、第九天 我趴在偏房一處隱蔽的房頂上張望栽连。 院中可真熱鬧,春花似錦侨舆、人聲如沸秒紧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熔恢。三九已至,卻和暖如春复颈,著一層夾襖步出監(jiān)牢的瞬間绩聘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工耗啦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凿菩,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓帜讲,卻偏偏與公主長得像衅谷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子似将,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容