Lambda表達式和函數式編程

Lambda表達式和函數式編程html

  http://www.javashuo.com/article/p-kcswmwel-bt.htmljava

  https://www.runoob.com/java/java8-lambda-expressions.htmlgit

函數接口是指內部只有一個接口函數的接口。express

1、Lambda表達式

  • 可選類型聲明:不須要聲明參數類型,編譯器能夠統一識別參數值。
  • 可選的參數圓括號:一個參數無需定義圓括號,但多個參數須要定義圓括號。
  • 可選的大括號:若是主體包含了一個語句,就不須要使用大括號。
  • 可選的返回關鍵字:若是主體只有一個表達式返回值則編譯器會自動返回值,大括號須要指定明表達式返回了一個數值。

在Lambda表達式以前,新建一個線程這樣寫:編程

new Thread(new Runnable(){
@Override
public void run(){
System.out.println("Thread run()");
}
}).start();ide

有Lambda表達式以後,則能夠這樣寫:
new Thread( () -> System.out.println("Thread run()") ).start();函數式編程

如上所示,Lambda表達式一個常見用法是取代(某些)匿名內部類,但Lambda表達式的做用不限於此。函數

Runnable run = () -> System.out.println("Hello World");// 1
ActionListener listener = event -> System.out.println("button clicked");// 2
Runnable multiLine = () -> {// 3
System.out.println("Hello ");
System.out.println("World");
};
BinaryOperator<Long> add = (Long x, Long y) -> x + y;// 4
BinaryOperator<Long> addImplicit = (x, y) -> x + y;// 5優化

2、Lambda表達式和Stream

Lambda表達式的另外一個重要用法,是和Stream一塊兒使用。
Stream is a sequence of elements supporting sequential and parallel aggregate operations。
Stream就是一組元素的序列,支持對這些元素進行各類操做,這些操做經過Lambda表達式指定。
能夠把Stream看做Java Collection的一種視圖,
就像迭代器是容器的一種視圖那樣(但Stream不會修改容器中的內容)。線程

下面例子展現了Stream的常見用法。

例子1
假設須要從一個字符串列表中選出以數字開頭的字符串並輸出,Java 7以前須要這樣寫:

List<String> list = Arrays.asList("1one", "two", "three", "4four");
for(String str : list){
if(Character.isDigit(str.charAt(0))){
System.out.println(str);
}
}

而Java 8就能夠這樣寫:

List<String> list = Arrays.asList("1one", "two", "three", "4four");
list.stream()// 1.獲得容器的Steam
.filter(str -> Character.isDigit(str.charAt(0)))// 2.選出以數字開頭的字符串
.forEach(str -> System.out.println(str));// 3.輸出字符串

上述代碼首先1. 調用List.stream()方法獲得容器的Stream,2. 而後調用filter()方法過濾出以數字開頭的字符串,3. 最後調用forEach()方法輸出結果。

使用Stream有兩個明顯的好處:

減小了模板代碼,只用Lambda表達式指明所需操做,代碼語義更加明確、便於閱讀。
將外部迭代改爲了Stream的內部迭代,方便了JVM自己對迭代過程作優化(好比能夠並行迭代)。

例子2
假設須要從一個字符串列表中,選出全部不以數字開頭的字符串,將其轉換成大寫形式,並把結果放到新的集合當中。Java 8書寫的代碼以下:

List<String> list = Arrays.asList("1one", "two", "three", "4four");
Set<String> newList =
list.stream()// 1.獲得容器的Stream
.filter(str -> !Character.isDigit(str.charAt(0)))// 2.選出不以數字開頭的字符串
.map(String::toUpperCase)// 3.轉換成大寫形式
.collect(Collectors.toSet());// 4.生成結果集

上述代碼
1.調用List.stream()方法獲得容器的Stream
2.調用filter()方法選出不以數字開頭的字符串
3.調用map()方法將字符串轉換成大寫形式
4.調用collect()方法將結果轉換成Set。
這個例子還向咱們展現了方法引用(代碼標號3處)以及收集器(代碼標號4處)的用法

經過這個例子咱們看到了Stream鏈式操做,即多個操做能夠連成一串。不用擔憂這會致使對容器的屢次迭代,由於不是每一個Stream的操做都會當即執行。Stream的操做分紅兩類,一類是中間操做(intermediate operations),另外一類是結束操做(terminal operation),只有結束操做纔會致使真正的代碼執行,中間操做只會作一些標記,表示須要對Stream進行某種操做。這意味着能夠在Stream上經過關聯多種操做,但最終只須要一次迭代。若是你熟悉Spark RDD,對此應該並不陌生。

相關文章
相關標籤/搜索