你們有沒有發現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.Iterable
的forEach
方法: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
啊。這不怪你們,由於「它們都是無心義的」,就像在這裏,你根本不須要知道咱們其實最後是調用的了Consumer
的accept
方法。
其實啊,全部java.util.function包下的接口的方法名,咱們都沒必要關心,由於當咱們用它們的時候,壓根不會去顯式地調用它們,方法名也是「無心義」的,它們只是方便你們去理解他的用途。可是,方法的參數和返回值是須要咱們關心和注意的。繼承
function
包下總共有43個接口,嗯~看上去數量仍是很多。沒必要懼怕,其實滿打滿算也就這麼5類:Function
、Supplier
、Consumer
、Predicate
、Operator
。這麼看就不多了吧。這還不僅,它們還有不少類似的地方,我們再根據這些類似點分類、觸類旁通,就會簡單不少。這裏先按照這些共性的點,給這43個接口細分下歸類:接口
Function類io
一元:Function
原始類型
DoubleFunction
,IntFunction
,LongFunction
ToDoubleFunction
,ToIntFunction
,ToLongFunction
DoubleToIntFunction
,DoubleToLongFunction
,IntToDoubleFunction
,IntToLongFunction
,LongToDoubleFunction
,LongToIntFunction
二元:BiFunction
原始類型
ToDoubleBiFunction
,ToIntBiFunction
,ToLongBiFunction
Supplier類
一元:Supplier
原始類型
BooleanSupplier
,DoubleSupplier
,IntSupplier
,LongSupplier
Consumer類
一元:Consumer
原始類型
DoubleConsumer
,IntConsumer
,LongConsumer
二元:BiConsumer
原始類型
ObjDoubleConsumer
,ObjIntConsumer
,ObjLongConsumer
Predicate類
一元:Predicate
原始類型
DoublePredicate
,IntPredicate
,LongPredicate
BiPredicate
Operator類
一元:UnaryOperator
原始類型
DoubleUnaryOperator
,IntUnaryOperator
, LongUnaryOperator
二元:BinaryOperator
原始類型
DoubleBinaryOperator
,IntBinaryOperator
,LongBinaryOperator
「額~彬哥,你這麼把它們都列出來,搞得我更暈啦!」別擔憂,對於它們每一類、每個接口究竟是什麼?怎麼用?我們後面的章節都會一一具體說明。這個分類,一來,能夠幫助你們先有個大致上的認識;二來,也能夠做爲後面章節的一個大綱,同時方便你們搞忘的時候來查閱。