'牛逼哄哄的 Lambda 表達式'

Java Java從算法到架構 2019-08-17
"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

只有當Optional<T>結合Lambda一起使用的時候,才能發揮出其真正的威力!


我們現在就來對比一下下面四種常見的null處理中,Java 8的Lambda+Optional<T>和傳統Java兩者之間對於null的處理差異。

情況一 - 存在則開幹

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

只有當Optional<T>結合Lambda一起使用的時候,才能發揮出其真正的威力!


我們現在就來對比一下下面四種常見的null處理中,Java 8的Lambda+Optional<T>和傳統Java兩者之間對於null的處理差異。

情況一 - 存在則開幹

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

只有當Optional<T>結合Lambda一起使用的時候,才能發揮出其真正的威力!


我們現在就來對比一下下面四種常見的null處理中,Java 8的Lambda+Optional<T>和傳統Java兩者之間對於null的處理差異。

情況一 - 存在則開幹

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況二 - 存在則返回,無則返回屁

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

只有當Optional<T>結合Lambda一起使用的時候,才能發揮出其真正的威力!


我們現在就來對比一下下面四種常見的null處理中,Java 8的Lambda+Optional<T>和傳統Java兩者之間對於null的處理差異。

情況一 - 存在則開幹

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況二 - 存在則返回,無則返回屁

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

只有當Optional<T>結合Lambda一起使用的時候,才能發揮出其真正的威力!


我們現在就來對比一下下面四種常見的null處理中,Java 8的Lambda+Optional<T>和傳統Java兩者之間對於null的處理差異。

情況一 - 存在則開幹

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況二 - 存在則返回,無則返回屁

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況三 - 存在則返回,無則由函數產生

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

只有當Optional<T>結合Lambda一起使用的時候,才能發揮出其真正的威力!


我們現在就來對比一下下面四種常見的null處理中,Java 8的Lambda+Optional<T>和傳統Java兩者之間對於null的處理差異。

情況一 - 存在則開幹

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況二 - 存在則返回,無則返回屁

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況三 - 存在則返回,無則由函數產生

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

只有當Optional<T>結合Lambda一起使用的時候,才能發揮出其真正的威力!


我們現在就來對比一下下面四種常見的null處理中,Java 8的Lambda+Optional<T>和傳統Java兩者之間對於null的處理差異。

情況一 - 存在則開幹

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況二 - 存在則返回,無則返回屁

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況三 - 存在則返回,無則由函數產生

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況四 - 奪命連環null檢查

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

只有當Optional<T>結合Lambda一起使用的時候,才能發揮出其真正的威力!


我們現在就來對比一下下面四種常見的null處理中,Java 8的Lambda+Optional<T>和傳統Java兩者之間對於null的處理差異。

情況一 - 存在則開幹

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況二 - 存在則返回,無則返回屁

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況三 - 存在則返回,無則由函數產生

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況四 - 奪命連環null檢查

牛逼哄哄的 Lambda 表達式

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

只有當Optional<T>結合Lambda一起使用的時候,才能發揮出其真正的威力!


我們現在就來對比一下下面四種常見的null處理中,Java 8的Lambda+Optional<T>和傳統Java兩者之間對於null的處理差異。

情況一 - 存在則開幹

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況二 - 存在則返回,無則返回屁

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況三 - 存在則返回,無則由函數產生

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況四 - 奪命連環null檢查

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


由上述四種情況可以清楚地看到,Optional<T>+Lambda可以讓我們少寫很多ifElse塊。尤其是對於情況四那種奪命連環null檢查,傳統java的寫法顯得冗長難懂,而新的Optional<T>+Lambda則清新脫俗,清楚簡潔。

"

1什麼是Lambda?


我們知道,對於一個Java變量,我們可以賦給其一個“值”

牛逼哄哄的 Lambda 表達式

如果你想把“一塊代碼”賦給一個Java變量,應該怎麼做呢?

比如,我想把右邊那塊代碼,賦給一個叫做aBlockOfCode的Java變量:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

在Java 8之前,這個是做不到的。但是Java 8問世之後,利用Lambda特性,就可以做到了。推薦:JDK8新特性之Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

當然,這個並不是一個很簡潔的寫法。所以,為了使這個賦值操作更加elegant, 我們可以移除一些沒用的聲明。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就成功的非常優雅的把“一塊代碼”賦給了一個變量。而“這塊代碼”,或者說“這個被賦給一個變量的函數”,就是一個Lambda表達式

但是這裡仍然有一個問題,就是變量aBlockOfCode的類型應該是什麼?

在Java 8裡面,所有的Lambda的類型都是一個接口,而Lambda表達式本身,也就是”那段代碼“,需要是這個接口的實現。這是我認為理解Lambda的一個關鍵所在,簡而言之就是,Lambda表達式本身就是一個接口的實現。直接這樣說可能還是有點讓人困擾,我們繼續看看例子。我們給上面的aBlockOfCode加上一個類型:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這種只有一個接口函數需要被實現的接口類型,我們叫它”函數式接口“。為了避免後來的人在這個接口中增加接口函數導致其有多個接口函數需要被實現,變成"非函數接口”,我們可以在這個上面加上一個聲明@FunctionalInterface, 這樣別人就無法在裡面添加新的接口函數了:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這樣,我們就得到了一個完整的Lambda表達式聲明:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

2Lambda表達式有什麼作用?


最直觀的作用就是使得代碼變得異常簡潔。


我們可以對比一下Lambda表達式和傳統的Java對同一個接口的實現:

牛逼哄哄的 Lambda 表達式


這兩種寫法本質上是等價的。但是顯然,Java 8中的寫法更加優雅簡潔。並且,由於Lambda可以直接賦值給一個變量,我們就可以直接把Lambda作為參數傳給函數, 而傳統的Java必須有明確的接口實現的定義,初始化才行:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


有些情況下,這個接口實現只需要用到一次。傳統的Java 7必須要求你定義一個“汙染環境”的接口實現MyInterfaceImpl,而相較之下Java 8的Lambda, 就顯得乾淨很多。

牛逼哄哄的 Lambda 表達式

Lambda結合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代碼變的更加簡潔!


直接上例子。

假設Person的定義和List<Person>的值都給定。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

現在需要你打印出guiltyPersons List裡面所有LastName以"Z"開頭的人的FirstName。


原生態Lambda寫法:定義兩個函數式接口,定義一個靜態函數,調用靜態函數並給參數賦值Lambda表達式。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

這個代碼實際上已經比較簡潔了,但是我們還可以更簡潔麼?


當然可以。在Java 8中有一個函數式接口的包,裡面定義了大量可能用到的函數式接口(java.util.function (Java Platform SE 8 ))。

所以,我們在這裡壓根都不需要定義NameChecker和Executor這兩個函數式接口,直接用Java 8函數式接口包裡的Predicate<T>和Consumer<T>就可以了——因為他們這一對的接口定義和NameChecker/Executor其實是一樣的。

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第一步簡化 - 利用函數式接口包:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


靜態函數裡面的for each循環其實是非常礙眼的。這裡可以利用Iterable自帶的forEach()來替代。forEach()本身可以接受一個Consumer<T> 參數。


第二步簡化 - 用Iterable.forEach()取代foreach loop:


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

由於靜態函數其實只是對List進行了一通操作,這裡我們可以甩掉靜態函數,直接使用stream()特性來完成。stream()的幾個方法都是接受Predicate<T>,Consumer<T>等參數的(java.util.stream (Java Platform SE 8 ))。你理解了上面的內容,stream()這裡就非常好理解了,並不需要多做解釋。


第三步簡化 - 利用stream()替代靜態函數:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

對比最開始的Lambda寫法,這裡已經非常非常簡潔了。但是如果,我們要求變一下,變成print這個人的全部信息,及p -> System.out.println(p); 那麼還可以利用Method reference來繼續簡化。所謂Method reference, 就是用已經寫好的別的Object/Class的method來代替Lambda expression。格式如下:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


第四步簡化 - 如果是println(p),則可以利用Method reference代替forEach中的Lambda表達式:

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


這基本上就是能寫的最簡潔的版本了。

牛逼哄哄的 Lambda 表達式

Lambda配合Optional<T>可以使Java對於null的處理變的異常優雅

這裡假設我們有一個person object,以及一個person object的Optional wrapper:

牛逼哄哄的 Lambda 表達式

Optional<T>如果不結合Lambda使用的話,並不能使原來繁瑣的null check變的簡單。


牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

只有當Optional<T>結合Lambda一起使用的時候,才能發揮出其真正的威力!


我們現在就來對比一下下面四種常見的null處理中,Java 8的Lambda+Optional<T>和傳統Java兩者之間對於null的處理差異。

情況一 - 存在則開幹

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況二 - 存在則返回,無則返回屁

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況三 - 存在則返回,無則由函數產生

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式

情況四 - 奪命連環null檢查

牛逼哄哄的 Lambda 表達式

牛逼哄哄的 Lambda 表達式


由上述四種情況可以清楚地看到,Optional<T>+Lambda可以讓我們少寫很多ifElse塊。尤其是對於情況四那種奪命連環null檢查,傳統java的寫法顯得冗長難懂,而新的Optional<T>+Lambda則清新脫俗,清楚簡潔。

牛逼哄哄的 Lambda 表達式

關於Java的Lambda, 還有東西需要討論和學習。比如如何handle lambda exception,如何利用Lambda的特性來進行parallel processing等。

總之,我只是一如既往地介紹個大概,讓你大概知道,哦!原來是這樣子就OK了。網上關於Lambda有很多相關的教程,多看多練。假以時日,必定有所精益

"

相關推薦

推薦中...