Java8-4-stream api和函數式編程簡單應用

上一篇文章中,咱們介紹了幾個Java8內置的函數式接口的特色和使用方式,並在最後引出了stream api的知識點,接下來咱們開始學習Java8中的stream api。
先假設一個簡單的需求,存在一個字符串集合,咱們想把全部長度大於5的字符串轉換成大寫輸出到控制檯,以前咱們可能會直接這麼作編程

public class Test3 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello","world","helloworld");

        for (int i = 0; i < list.size(); i++) {
            if(list.get(i).length() > 5){
                System.out.println(list.get(i).toUpperCase());
            }
        }
    }
}

如今換成使用stream api看下segmentfault

public class Test3 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello","world","helloworld");
        list.stream().filter(s -> s.length() > 5).map(s -> s.toUpperCase()).forEach(System.out::println);
    }
}

1行代碼直接搞定,並且這種鏈式編程風格從語義上看邏輯很清晰。
stream方法先構造了一個該集合的Stream對象,filter方法取出長度大於5的字符串,map方法將全部字符串轉大寫,forEach輸出到控制檯。咱們能夠對照Stream接口的源碼片斷看下這幾個stream api的定義api

public interface Stream<T> extends BaseStream<T, Stream<T>> {
    
    Stream<T> filter(Predicate<? super T> predicate);
    
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);
    
    void forEach(Consumer<? super T> action);
    .
    .省略
    .
}

filter方法,接收一個Predicate函數式接口類型做爲參數,並返回一個Stream對象,從上一篇咱們知道能夠由一個接收一個參數返回布爾類型的lambda表達式來建立Predicate函數式接口實例,因此看到filter接收的參數是s -> s.length() > 5app

map方法,接收Function函數式接口類型,接收一個參數,有返回值s -> s.toUpperCase() 正是作了這件事情函數式編程

forEach方法,接收Consumer函數式接口類型,接收一個參數,不返回值 這裏使用方法引用的其中一種形式System.out::println來建立了Consumer實例。函數

因此經過上面的例子能夠看出函數式編程和stream api結合的很是緊密。你們應該也注意到了在介紹每一個方法時,咱們提到了有中間操做和終止操做,終止操做意味着咱們須要一個結果了,當程序遇到終止操做時纔會真正執行。中間操做是指在終止操做以前全部的方法,這些方法以方法鏈的形式組織在一塊兒處理一些列邏輯,若是隻有中間操做而沒有終止操做的話即便運行程序,代碼也不會執行的學習

實際上map方法中能夠使用另外一種方法引用的形式來處理,類方法引用。語法:類名::方法名code

public class Test3 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello","world","helloworld");
        list.stream().filter(s -> s.length() > 5).map(String::toUpperCase).forEach(System.out::println);
    }
}

以前介紹的System.out::println這種屬於對象方法引用,類方法引用的應用也是很普遍的。只是理解起來須要花費些時間,map方法接收一個Function函數式接口的實現,那就確定須要一個輸入而且有一個輸出,可是咱們看下toUpperCase方法的定義對象

public String toUpperCase() {
    return toUpperCase(Locale.getDefault());
}

有返回值,可是沒有入參,乍一看也不符合Function接口中apply方法的定義啊。這也是類方法引用的特色,雖然toUpperCase沒有明確的入參,由於此時toUpperCase的輸入是調用它的那個對象,編譯器會把調用toUpperCase方法的那個對象當作參數,也就是lambda表達式s -> s.toUpperCase()中的s參數。因此也知足一個輸入一個輸出的定義。接口

小結:本篇簡單介紹了函數式編程與stream api應用及類方法引用的使用,lambda表達式讓老版本的代碼更簡潔,方法引用讓lambda表達式更簡潔,實際上就是lambda表達式的一種語法糖。

下一篇

相關文章
相關標籤/搜索