function包概述及大綱

你們有沒有發現java.util.function包(本文後面簡稱function包)下的接口雖然比較多(目前共43個),但都是定義很簡單的(方法不多),而咱們理解起來卻十分的困難。其實啊,這也不怪你們,是由於這個包下的接口並非典型的Java的API,你能夠說它們是「異類」。那麼問題來了,典型的Java API是什麼樣子的呢?function包下的接口又「異」在哪裏?java

總所周知,Java是一種典型的OOP面向對象編程)語言,封裝、繼承、多態自沒必要多說,你們想必都十分清楚了。但這裏爲了解釋上面的問題,彬哥仍是得多囉嗦幾句。面向對象一個很重要的標識就是,把結構和行爲封裝到一個類(對象)中。編程

典型的Java API就是這樣子的,舉個你們都很熟悉的例子:java.util.List。List是一個接口,是接口就只有方法,沒有屬性。可是,我們來看看的List中的方法:size()、isEmpty()、contains(Object o)等等,按照正常人的思惟,很容易、也很天然會將這些方法理解成:「假設我是個List的對象(實例)話,大家調用個人size()方法,我會將個人size告訴你;調用個人isEmpty()方法,我會告訴你我是否是空的;調用個人contains()方法,我會告訴你我是否是包含了你指定的這個對象」。你們有沒有發現點什麼?全部這些方法,很天然的加入到「我」這個語境(context)中去了。函數

那麼再來看看這個我們這個專題的主角function包看,找個典型表明出來:java.util.function.Consumer<T>Consumer是個Functional接口,有且只有一個「抽象方法」--void accept(T t)。這個accept方法誰能告訴我這™是什麼鬼?彬哥如今也不知道,這還真不是彬哥故意賣關子。這是由於啊,你能夠function包下的接口都是「無心義的」,這個「無心義」並非說它們沒有存在的意義,而是說它們都必須放到具體的語境中去纔會真正的意義。或者說,它們是「非典型」的Java API就體如今,它們本身是沒有語境(Context)的,它們實際上能夠說就是爲Lambda表達式而存在的--你不須要了解他叫什麼(匿名的),它們是做爲參數在對象的方法的中傳遞的。ui

它們沒有本身的結構,只定義行爲,這很不OOP,但很FP(Functional Programming),因此你能夠說,從JDK 8開始,函數也能夠被稱做Java世界中的「第一公民」了。this

來看個具體的例子,java.lang.IterableforEach方法:code

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

它的參數就是個Consumer,從forEach這個方法的定義來看,如今咱們能夠理解到「遍歷我所包含的全部元素,對每一個元素都執行一次action.accept()」,還有點抽象?不過已經有些好理解了是吧?我們再進一步看:對象

List<String> list = new ArrayList<>();
list.add("Hello ");
list.add("彬哥!");
list.forEach(s -> System.out.println(s)); // 這裏固然也能夠用更爲簡潔的方法引用來改寫

如今在具體的語境裏來理解就很容易了,「對於list中的每個元素,執行我傳進去的那個函數--Consumer」。可能我們天天都在用相似的寫法,但可能歷來都沒有意識到,那原來就是個Consumer啊。這不怪你們,由於「它們都是無心義的」,就像在這裏,你根本不須要知道咱們其實最後是調用的了Consumeraccept方法。
其實啊,全部java.util.function包下的接口的方法名,咱們都沒必要關心,由於當咱們用它們的時候,壓根不會去顯式地調用它們,方法名也是「無心義」的,它們只是方便你們去理解他的用途。可是,方法的參數和返回值是須要咱們關心和注意的。繼承

function包下總共有43個接口,嗯~看上去數量仍是很多。沒必要懼怕,其實滿打滿算也就這麼5類:
FunctionSupplierConsumerPredicateOperator。這麼看就不多了吧。這還不僅,它們還有不少類似的地方,我們再根據這些類似點分類、觸類旁通,就會簡單不少。這裏先按照這些共性的點,給這43個接口細分下歸類:接口

  • Function類io

    • 一元:Function

      • 原始類型

        • 做爲參數:DoubleFunctionIntFunctionLongFunction
        • 做爲返回值:ToDoubleFunctionToIntFunctionToLongFunction
        • 相互轉化:DoubleToIntFunctionDoubleToLongFunctionIntToDoubleFunctionIntToLongFunctionLongToDoubleFunctionLongToIntFunction
    • 二元:BiFunction

      • 原始類型

        • 做爲返回值:ToDoubleBiFunctionToIntBiFunctionToLongBiFunction
  • Supplier類

    • 一元:Supplier

      • 原始類型

        • 做爲返回值:BooleanSupplierDoubleSupplierIntSupplierLongSupplier
  • Consumer類

    • 一元:Consumer

      • 原始類型

        • 做爲參數:DoubleConsumerIntConsumerLongConsumer
    • 二元:BiConsumer

      • 原始類型

        • 做爲參數:ObjDoubleConsumerObjIntConsumerObjLongConsumer
  • Predicate類

    • 一元:Predicate

      • 原始類型

        • 做爲參數:DoublePredicateIntPredicateLongPredicate
    • 二元:BiPredicate
  • Operator類

    • 一元:UnaryOperator

      • 原始類型

        • 同時做爲參數和返回值:DoubleUnaryOperatorIntUnaryOperatorLongUnaryOperator
    • 二元:BinaryOperator

      • 原始類型

        • 同時做爲參數和返回值:DoubleBinaryOperatorIntBinaryOperatorLongBinaryOperator

「額~彬哥,你這麼把它們都列出來,搞得我更暈啦!」別擔憂,對於它們每一類、每個接口究竟是什麼?怎麼用?我們後面的章節都會一一具體說明。這個分類,一來,能夠幫助你們先有個大致上的認識;二來,也能夠做爲後面章節的一個大綱,同時方便你們搞忘的時候來查閱。

相關文章
相關標籤/搜索