Java 8的核心新特性:Lambda(匿名函數)、流、默認方法

Java 中的函數

Java 8中新增了函數——值的一種新形式。函數做爲一等值,使用方法引用 :: 語法(即「把這個方法做爲值」),做爲函數式值來傳遞。html

File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
    public boolean accept(File file) {
         return file.isHidden();
    }
});

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

File[] hiddenFiles = new File(".").listFiles(File::isHidden);

Lambda——匿名函數

除了容許(命名)函數成爲一等值外,Java 8還體現了更廣義的將函數做爲值的思想,包括Lambda(或匿名函數)。能夠把Lambda表達式理解爲簡潔地表示可傳遞的匿名函數的一種方式:它沒有名稱,但它有參數列表、函數主體、返回類型,可能還有一個能夠拋出的異常列表。express

Lambda表達式由參數、箭頭和主體組成。在函數式接口上使用Lambda表達式。app

函數式接口就是隻定義一個抽象方法的接口。函數

Lambda的基本語法是this

(parameters) -> expression

或(請注意語句的花括號)lua

(parameters) -> { statements; }

下面給出了Java 8中五個有效的Lambda表達式的例子。spa

// 1
(String s) -> s.length()

// 2
(Apple a) -> a.getWeight() > 150

// 3
(int x, int y) -> {
   System.out.println("Result:");
   System.out.println(x+y);
}

// 4
() -> 42

// 5
(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())

第一個Lambda表達式具備一個 String 類型的參數並返回一個 int 。Lambda沒有 return 語句,由於已經隱含了 return。設計

第二個Lambda表達式有一個Apple 類 型 的參數並返回一個 boolean (蘋果的重量是否超過150克)。code

第三個Lambda表達式具備兩個 int 類型的參數而沒有返回值( void 返回)。注意Lambda表達式能夠包含多行語句,這裏是兩行。

第四個Lambda表達式沒有參數,返回一個int 。

第五個Lambda表達式具備兩個 Apple 類型的參數,返回一個 int :比較兩個 Apple 的重量。

和Collection API相比,Stream API處理數據的方式很是不一樣。用集合的話,你得本身去作迭代的過程。你得用 for-each 循環一個個去迭代元素,而後再處理元素。咱們把這種數據迭代的方法稱爲外部迭代。相反,有了Stream API,你根本用不着操心循環的事情。數據處理徹底是在庫內部進行的。咱們把這種思想叫做內部迭代

Collection主要是爲了存儲和訪問數據,而Stream則主要用於描述對數據的計算。這裏的關鍵點在於,Stream容許並提倡並行處理一個 Stream 中的元素。雖然可能乍看上去有點兒怪,但篩選一個 Collection 的最快方法經常是將其轉換爲 Stream ,進行並行處理,而後再轉換回 List 。 

好比,利用Stream和Lambda表達式順序或並行地從一個列表裏篩選比較重的蘋果。

import static java.util.stream.Collectors.toList;

List<Apple> inventory = Arrays.asList(new Apple(80,"green"),
                                      new Apple(155, "green"),
                                      new Apple(120, "red"));	

List<Apple> apples = inventory.stream()
                .filter((Apple a) -> a.getWeight() > 150)
                .collect(toList());

// 並行處理
List<Apple> apples2 = inventory.parallelStream()
                .filter((Apple a) -> a.getWeight() > 150)
                .collect(toList());

filter方法傳入的參數實際上是謂詞,咱們來看下JDK8 Predicate類源碼。

package java.util.function;

import java.util.Objects;

/**
 * Represents a predicate (boolean-valued function) of one argument.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #test(Object)}.
 *
 * @param <T> the type of the input to the predicate
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);

    // ...
}

什麼是謂詞?

謂詞(predicate)在數學上經常用來表明一個相似函數的東西,它接受一個參數值,並返回 true 或 false 。

filter經過行爲參數化進行代碼傳遞。行爲參數化,就是一個方法接受多個不一樣的行爲做爲參數,並在內部使用它們,完成不一樣行爲的能力。其實就是策略模式,它能夠把一個行爲(一段代碼)封裝起來,並經過傳遞和使用建立的行爲(例如不一樣謂詞)將方法的行爲參數化。行爲參數化可讓代碼更好地適應不斷變化的要求,減輕將來的工做量。

Java API中的不少方法均可以用不一樣的行爲來參數化(好比Comparator 排序,用 Runnable 執行一個代碼塊,以及GUI事件處理),這些方法每每與匿名類一塊兒使用。

默認方法

Java 8中加入默認方法主要是爲了支持庫設計師,讓他們可以寫出更容易改進的接口。在接口中使用默認方法,在實現類沒有實現方法時提供方法內容。在接口聲明中使用新的 default 關鍵字來表示這一點。

參考

書籍《Java 8實戰》

相關文章
相關標籤/搜索