記憶java.util.function包下的介面
函式式介面是java8新加入的重大更新。瞭解了lambda表示式之後也要了解jdk中已經寫好,給開發者呼叫的介面。這篇文章的目的幫助程式設計師記記java.util.function包下所有函式式介面。首先看看這個包下面介面的總量,嗯,一共43個,不少啊。
第一步
首先記住function包下的4個主要函式介面,我把它們叫作基本介面。其它的介面都是由這4個介面衍生來的,注意不是繼承。
-
Function
這裡的Function代表的含議其實就是中學學過的數學裡的函式y = f(x) 。介面中定義的抽象方法是
apply
,與數學中的定義一樣,這個方法也是接收一個輸入,返回一個輸出。 -
Consumer
這是消費者函式,介面中定義的抽象方法是
accept
。顧名恩義,接收一個引數,返回是void
, -
Supplier
這是生產者函式,介面中定義的抽象方法是
get
。不接收引數,有一個返回。 -
Predicate
斷言函式,介面中定義的抽象方法是
test
。接收一個引數,返回true
或者false
。
其實存細想想這些介面定義的名稱和介面的抽象方法都是具有含現實中的含義的,並不難記。4個介面者定義為範型,輸要使用者自己傳入。
目前記住了4個,還有39個。
第二步
我們觀察前面的4個介面,發現除了Supplier
介面不需要輸入,其它介面中的抽象方法接收一個輸入,那麼在實際的開發中接收兩個輸入的情況多不多呢?jdk作者認為接收兩個輸入的情況也很多,有必要再增加三個介面,接收兩個輸入。介面名稱分別是BiFunction、BiConsumer、 BiPredicate
。這三個介面的抽象方法名稱與上面的一樣。唯一的區別就是接收輸入的數量不同。
目前記住了7個,還剩下36個。
如果能記住這7個,實際上已經能充分利用這個java.util.function包下面定義的介面而不需要重新定義了,剩餘的36個介面完成是為了方從方便的角度上定義的,是為了錦上添花。
第三步
再來看生產者函式,不接收輸入,只有輸出。
java一共有8種基本型別,或者叫原始型別(primitive type)分別是:byte short int long float double boolean char
。那麼對於函式式介面每次使用的時候都用範型介面傳入型別實在是太麻煩了。開發者對於原生型別的使用是最常見的,有必要為這些原生型別專門定義介面而不是每次都要開發者傳入型別,這本來就是開發這些函式介面的目的。那麼難道把所有的型別全部定義一遍嗎,會產生大量的介面。jdk的開發者選擇了4個最常用的原始型別,分別是int long double boolean
。對應的介面名稱分別是IntSupplier LongSupplier DoubleSupplier BooleanSupplier
,對應的抽象方法名為getAsInt getAsLong getAsDouble getAsBoolean
。當然也很好記。
目前記住了11個,還剩下32個,而且把生產者介面全都記住了。
第四步
現在集中精力對付斷言函式。基本斷言函式的範型固定為int long double
,這樣又多了3個衍生的斷言函式。分別是IntPredicate LongPredicate DoublePredicate
,抽象方法名不變。當然接收的輸入資料型別分別為int long double
。
目前記住了14個,還剩下29個,把斷言介面全都記住了。
第五步
再來看消費者介面。jdk作者對於接收1個輸入和2個輸入的消費者介面都定義了特定的型別。
- 1個輸入的消費者介面
定義了IntCustomer LongCustomer DoubleCustomer
介面,抽象方法名稱不變。
- 2個輸入的消費者介面
定義了ObjIntCustomer ObjLongCustomer ObjDoubleCustomer
介面。介面定義的2個型別分別為範型和相應型別的包裝類。方法名稱也不變。
目前記住了20個,還剩下23個,把消費者介面也全都記住了。
第六步
沒錯,剩下的23個全部都是函式型別的介面。在這一步中我們要記住所有一元函式介面
- 返回為範型,接收3種基本型別包裝類
跟其它3種基本介面型別一樣,也定義了IntFunction LongFunction DoubleFunction
,抽象方法名也不變。
- Integer作為輸入,返回為2種基本型別包裝類
定義了IntToLongFunction IntToDoubleFunction
,抽象方法名分別為applyAsLong applyAsDouble
。
- Long作為輸入,返回為2個基本型別包裝類
定義了LongToIntFunction LongToDoubleFunction
,抽象方法名分別為applyAsInt applyAsDouble
。
- Double作為輸入,返回為2個基本型別包裝類
定義了DoubleToIntFunction DoubleToLongFunction
,抽象方法名分別為applyAsInt applyAsLong
。
- 3種基本型別包裝類作為輸入,輸出也是同樣的型別
定義了IntUnaryOperator LongUnaryOperator DoubleUnaryOperator
,抽象方法名分別為applyAsInt applyAsLong applyAsDouble
。這裡的Unary就是一元的意思,表示這個是一元函式。
- 範型作為輸入,輸出為範型和3種基本型別包裝類
定義了ToIntFunction ToLongFunction ToDoubleFunction UnaryOperator
,抽象方法分別為applyAsInt applyAsLong applyAsDouble UnaryOperator
。
目前記住了36個,還剩下7個。
第七步
現在沒有記住的介面只剩下接收2個輸入的函式型別的介面了。
- 2個輸入可以是不同範型,輸入為3種基本型別包裝類
定義了ToIntBiFunction ToLongBiFunction ToDoubleBiFunction
,抽象方法分別為applyAsInt applyAsLong applyAsDouble
- 2個輸入和1個輸出都是同一種類型,而且是範型
定義了BinaryOperator
,抽象方法為apply
。
- 2個輸入和1個輸出都是同一種類型,而且是3種基本型別包裝類
定義了IntBinaryOperator LongBinaryOperator DoubleBinaryOperator
,抽象方法分別為applyAsInt applyAsLong applyAsDouble
。
總結
實際上這個包下面的所有介面邏輯都是非常清晰的,只要掌握了jdk作者的分類方法就完全能記住。
對於程式設計師來說要學會查文件,但是如果沒有把一些常用的類和介面記在心裡那麼工作的效率就會變得很低。