JDK1.8新特性---lambda表達(dá)式

1.Lambda 表達(dá)式
首先看看在老版本的Java中是如何排列字符串的:
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});
只需要給靜態(tài)方法 Collections.sort 傳入一個(gè)List對象以及一個(gè)比較器來按指定順序排列。通常做法都是創(chuàng)建一個(gè)匿名的比較器對象然后將其傳遞給sort方法裆蒸。

在Java 8 中你就沒必要使用這種傳統(tǒng)的匿名對象的方式了,Java 8提供了更簡潔的語法佛致,lambda表達(dá)式:
Collections.sort(names, (String a, String b) -> {
return b.compareTo(a);
});
看到了吧辙谜,代碼變得更段且更具有可讀性,但是實(shí)際上還可以寫得更短:
Collections.sort(names, (String a, String b) -> b.compareTo(a));
對于函數(shù)體只有一行代碼的筷弦,你可以去掉大括號{}以及return關(guān)鍵字抑诸,但是你還可以寫得更短點(diǎn):
Collections.sort(names, (a, b) -> b.compareTo(a));
接下來我們看看lambda表達(dá)式還能作出什么更方便的東西來:

2爹殊、函數(shù)式接口
Lambda 表達(dá)式是如何在java的類型系統(tǒng)中表示的呢?每一個(gè)lambda表達(dá)式都對應(yīng)一個(gè)類型层玲,通常是接口類型反症。而“函數(shù)式接口”是指僅僅只包含一個(gè)抽象方法的 接口,每一個(gè)該類型的lambda表達(dá)式都會(huì)被匹配到這個(gè)抽象方法铅碍。因?yàn)?默認(rèn)方法 不算抽象方法,所以你也可以給你的函數(shù)式接口添加默認(rèn)方法尘盼。
我們可以將lambda表達(dá)式當(dāng)作任意只包含一個(gè)抽象方法的接口類型烦绳,確保你的接口一定達(dá)到這個(gè)要求,你只需要給你的接口添加 @FunctionalInterface 注解径密,編譯器如果發(fā)現(xiàn)你標(biāo)注了這個(gè)注解的接口有多于一個(gè)抽象方法的時(shí)候會(huì)報(bào)錯(cuò)的。
示例如下:

@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
驗(yàn)證: Converter<String, Integer> converter = new Converter<String, Integer()
{

        @Override
        public Integer converter(String form) {
            return Integer.valueOf(form);
        }
        
    };

    // 簡化
    converter = (String form) -> {return Integer.valueOf(form);};
    // 簡化
    converter = (form) -> Integer.valueOf(form);
    Integer integer = converter.converter("123");
    System.out.println(integer);

需要注意如果@FunctionalInterface如果沒有指定底桂,上面的代碼也是對的伪很。

3.方法與構(gòu)造函數(shù)引用
前一節(jié)中的代碼還可以通過靜態(tài)方法引用來表示:
Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted); // 123

Java 8 允許你使用 :: 關(guān)鍵字來傳遞方法或者構(gòu)造函數(shù)引用,上面的代碼展示了如何引用一個(gè)靜態(tài)方法猫十,我們也可以引用一個(gè)對象的方法:

    String something = "JavaEE";
    Converter<String, Boolean> converter1 = something::startsWith;
    boolean res = converter1.converter("Java");
    System.out.println(res);

接下來看看構(gòu)造函數(shù)是如何使用::關(guān)鍵字來引用的呆盖,首先我們定義一個(gè)包含多個(gè)構(gòu)造函數(shù)的簡單類:
class Person {
String firstName;
String lastName;
Person() {}
Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
接下來我們指定一個(gè)用來創(chuàng)建Person對象的對象工廠接口:

interface PersonFactory<P extends Person> {
P create(String firstName, String lastName);
}
這里我們使用構(gòu)造函數(shù)引用來將他們關(guān)聯(lián)起來,而不是實(shí)現(xiàn)一個(gè)完整的工廠:

PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");

我們只需要使用 Person::new 來獲取Person類構(gòu)造函數(shù)的引用宙项,Java編譯器會(huì)自動(dòng)根據(jù)PersonFactory.create方法的簽名來選擇合適的構(gòu)造函數(shù)株扛。

四汇荐、Lambda 作用域
在lambda表達(dá)式中訪問外層作用域和老版本的匿名對象中的方式很相似。你可以直接訪問標(biāo)記了final的外層局部變量掀淘,或者實(shí)例的字段以及靜態(tài)變量油昂。

五、訪問局部變量
我們可以直接在lambda表達(dá)式中訪問外層的局部變量:
復(fù)制代碼 代碼如下:

final int num = 1;
Converter<Integer, String> stringConverter =
(from) -> String.valueOf(from + num);
stringConverter.convert(2); // 3

但是和匿名對象不同的是冕碟,這里的變量num可以不用聲明為final,該代碼同樣正確:
復(fù)制代碼 代碼如下:

int num = 1;
Converter<Integer, String> stringConverter =
(from) -> String.valueOf(from + num);
stringConverter.convert(2); // 3

不過這里的num必須不可被后面的代碼修改(即隱性的具有final的語義)厕妖,例如下面的就無法編譯:
復(fù)制代碼 代碼如下:

int num = 1;
Converter<Integer, String> stringConverter =
(from) -> String.valueOf(from + num);
num = 3;

在lambda表達(dá)式中試圖修改num同樣是不允許的挑庶。
六、訪問對象字段與靜態(tài)變量
和本地變量不同的是,lambda內(nèi)部對于實(shí)例的字段以及靜態(tài)變量是即可讀又可寫埋嵌。該行為和匿名對象是一致的:
復(fù)制代碼 代碼如下:
class Lambda4 {
static int outerStaticNum;
int outerNum;
void testScopes() {
Converter<Integer, String> stringConverter1 = (from) -> {
outerNum = 23;
return String.valueOf(from);
};
Converter<Integer, String> stringConverter2 = (from) -> {
outerStaticNum = 72;
return String.valueOf(from);
};
}
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末雹嗦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子了罪,更是在濱河造成了極大的恐慌,老刑警劉巖泊藕,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娃圆,死亡現(xiàn)場離奇詭異,居然都是意外死亡讼呢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門节沦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人甫贯,你說我怎么就攤上這事±堤酰” “怎么了常熙?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長仿贬。 經(jīng)常有香客問我,道長茧泪,這世上最難降的妖魔是什么聋袋? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮嗜侮,結(jié)果婚禮上啥容,老公的妹妹穿的比我還像新娘锈颗。我一直安慰自己咪惠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布覆醇。 她就那樣靜靜地躺著炭臭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪徽缚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天排宰,我揣著相機(jī)與錄音,去河邊找鬼党瓮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛寞奸,可吹牛的內(nèi)容都是我干的在跳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瓷翻,長吁一口氣:“原來是場噩夢啊……” “哼割坠!你這毒婦竟也來了齐帚?” 一聲冷哼從身側(cè)響起彼哼,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤敢朱,失蹤者是張志新(化名)和其女友劉穎饥伊,沒想到半個(gè)月后蔫饰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愉豺,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蚪拦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了驰贷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡次兆,死狀恐怖锹锰,靈堂內(nèi)的尸體忽然破棺而出漓库,到底是詐尸還是另有隱情园蝠,我是刑警寧澤渺蒿,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布茂装,位于F島的核電站,受9級特大地震影響少态,放射性物質(zhì)發(fā)生泄漏挚冤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一训挡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧为肮,春花似錦肤京、人聲如沸颊艳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽重斑。三九已至肯骇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間笛丙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工骨稿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人啊终。 一個(gè)月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像趟脂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子昔期,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評論 2 354

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