第一章 爲何要關心java8

1、java怎麼還在變java

一、java在編程語言生態系統中的位置數據庫

java虛擬機(JVM)及其字節碼可能會變得比java語言自己更重要,並且對於某些應用來講,java可能會被一樣運行在JVM上的競爭對手(如Scala或Groovv)取代。編程

二、流處理安全

(1)、第一個編程概念就是流處理。介紹一下,流是一系列數據項,一次只生成一項。程序能夠從輸入流中一個一個讀取數據項,而後以一樣的方式將數據項寫入輸入流。一個程序的輸出流多是另外一個程序的輸入流。多線程

(2)、先把字母轉換成小寫字母,而後打印出按照字典排序出如今最後的三個單詞。其中cat,tr,sort,tail是同時執行的,這樣sort就能夠在cat或tr完成前先處理頭幾行。app

(3)、在一個更高的抽象層次上寫java8程序:思路變成了把這樣的流變成那樣的流(就像寫數據庫查詢語句時的那種思路),而不是一次只處理一個項目。另外一個好處是,java8能夠透明地把輸入的不想管部分拿到幾個cpu內核上去分別執行你的Stream操做流水線——這是幾乎免費的並行,用不着費勁搞Thead了。編程語言

三、用行爲參數把代碼傳遞給方法函數式編程

java8加強了把方法(你的代碼)做爲參數傳遞給另外一個方法的能力函數

四、並行與共享的可變數據線程

"不能有共享的可變數據"的要求意味着,一個方法能夠經過它將參數值轉換爲結果的方式徹底描述的,換句話說,他的行爲就像一個數據函數,沒有可見的反作用。

2、java中的函數

對象是java中的一等公民,但其餘不少java概念(如方法和類等)都是二等公民。

一、方法和lambda做爲一等公民

(1)方法引用

File [] hiddenFiles = new File(".").listFiles(File::isHidden); 已經有了函數isHidden,所以只須要用java 8的方法引用::語法(即「把這個方法做爲值」)將其傳遞給listFiles方法。

只要方法中有代碼(方法中的可執行部分),那麼用方法引用就能夠傳遞代碼。

(2)Lambda——匿名函數

除了容許(命名)函數成爲一等值外,java8還體現了更廣義的將函數做爲值的思想,包括Lambda(或匿名函數)。

二、傳遞代碼:一個例子

public static boolean isGreenApple(Apple apple) {
    return "green".equals(apple.getColor()); 
}

public static boolean isHeavyApple(Apple apple) {
    return apple.getWeight() > 150;
}

public static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p){
    List<Apple> result = new ArrayList<>();
    for(Apple apple : inventory){
        if(p.test(apple)){
            result.add(apple);
        }
    }
    return result;
}   

List<Apple> inventory = Arrays.asList(new Apple(80,"green"),
                                      new Apple(155, "green"),
                                      new Apple(120, "red"));  
List<Apple> greenApples = filterApples(inventory, FilteringApples::isGreenApple);
System.out.println(greenApples);
List<Apple> heavyApples = filterApples(inventory, FilteringApples::isHeavyApple);
System.out.println(heavyApples);

三、從傳遞方法到Lambda

// [Apple{color='green', weight=80}, Apple{color='green', weight=155}]
List<Apple> greenApples2 = filterApples(inventory, (Apple a) -> "green".equals(a.getColor()));
System.out.println(greenApples2);

// [Apple{color='green', weight=155}]
List<Apple> heavyApples2 = filterApples(inventory, (Apple a) -> a.getWeight() > 150);
System.out.println(heavyApples2);

// []
List<Apple> weirdApples = filterApples(inventory, (Apple a) -> a.getWeight() < 80 || 
                                                               "brown".equals(a.getColor()));
System.out.println(weirdApples);

3、流

一、例如:從一個列表中篩選金額較高的交易

(1)傳統代碼:這種數據迭代的方法稱爲外部迭代

(2)Steam API:數據處理徹底是在庫內部進行的,這種思想叫作內部迭代。

二、多線程並不是易事

(1)線程可能會同時訪問並更新共享變量。所以,若是沒有協調好,數據可能會被之外改變,相比一步步執行的順序模型,這個模型不太好理解。

(2)java8也用Stream API解決了這兩個問題:集合處理時的套路和晦澀,以及難以利用多核。

(3)Collection主要是爲了存儲和訪問數據,而Stream則主要用於描述對數據的計算。這裏的關鍵點在於,Stream容許並提倡並行處理一個Stream中的元素。篩選一個Collection的最快方法經常是將其轉換爲Stream。進行並行處理,而後再轉換會List。

順序處理:

import static java.util.stream.Collectors.toList;
List<Apple> heavyApples = inventory.stream().filter((Apple a) ->a.getWeight()>150).collect(toList());

並行處理:

import static java.util.stream.Collectors.toList;
List<Apple> heavyApples = inventory.parallelStream().filter((Apple a) ->a.getWeight()>150).collect(toList());

4、默認方法

java8接口現在能夠包含實現類沒有提供實現的方法簽名,缺失的方法主體隨接口提供了(所以就有了默認實現),而不是有由實現類提供。

5、來自函數式編程的其餘好思想

將方法和lambda做爲一等值,以及在沒有可變共享狀態時,函數 或方法能夠有效、安全的並行執行。

相關文章
相關標籤/搜索