學習JDK8新特性,必不可少的就是函數式編程,那也就不得不瞭解Function接口的使用了。java
首先看下Function接口的定義編程
@FunctionalInterface public interface Function<T, R>{ /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); // 省略其餘方法 }
接口定義了兩個泛型,在使用的時候須要指定。app
該接口中比較重要的就是這個apply方法,其參數是類型T,返回時類型R(可能這麼描述不太合適)函數式編程
接下來看下Map中的新方法(該方法的詳解能夠參考個人另外一篇博客https://my.oschina.net/simpleton/blog/1552737)函數
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { Objects.requireNonNull(mappingFunction); V v; if ((v = get(key)) == null) { V newValue; if ((newValue = mappingFunction.apply(key)) != null) { put(key, newValue); return newValue; } } return v; }
這個方法第一個參數是Map的key,第二個參數就是一個函數接口,在該方法內部調用了apply(key)。學習
好的,咱們來看看如何使用這個方法ui
String[] data = "1 2 3 4 1 2 3 1 2 1".split(" "); HashMap<String, LinkedList<String>> map1 = new HashMap<>(); for (String s : data) { map1.computeIfAbsent(s, s1 -> new LinkedList<>()).add(s); } System.out.println("map1 = " + map1);
上面方法的輸出結果以下:this
map1 = {1=[1, 1, 1, 1], 2=[2, 2, 2], 3=[3, 3], 4=[4]}.net
說明下這段代碼code
map1.computeIfAbsent(s, s1 -> new LinkedList<>()).add(s);
map1對象調用computeIfAbsent方法,傳入了2個參數,s是map1中的key,第二個是一段函數定義,s1是函數的參數,new LinkedList<>()是函數的實現,實際上這是一個縮寫,完整寫法以下
map1.computeIfAbsent(s, (s1) -> {return new LinkedList<>();}).add(s);
對於只有一個參數的函數代碼,能夠省略(),即只須要寫s1,函數實現若是隻有一行代碼,能夠省略{}和return。
好了,而後就是computeIfAbsent內部的執行了,其實核心就是mappingFunction.apply(key),能夠看到,調用apply方法的時候,傳入的參數其實是key,也就是computeIfAbsent的第一個參數,那麼回過頭來看map1.computeIfAbsent(s, s1 -> new LinkedList<>()).add(s);這段代碼中的s和s1在函數代碼(s1 -> new LinkedList<>())運行的時候,其實s1的值就是s的值。很混亂是不?咱們再來看段代碼
String[] data = "1 2 3 4 1 2 3 1 2 1".split(" "); HashMap<String, LinkedList<String>> map1 = new HashMap<>(); for (String s : data) { map1.computeIfAbsent(s, s1 -> {LinkedList list = new LinkedList<>();list.add(s1);return list;}).add(s); //map1.computeIfAbsent(s, s1 -> new LinkedList<String>()).add(s); } System.out.println("map1 = " + map1);
上面的輸出結果以下:
map1 = {1=[1, 1, 1, 1, 1], 2=[2, 2, 2, 2], 3=[3, 3, 3], 4=[4, 4]}
爲何呢?由於咱們定義的函數s1 -> {LinkedList list = new LinkedList<>();list.add(s1);return list;}實現中,將參數s1也放進了新建立的集合中。
到這裏,基本上已經說明了Function接口的如何在實際中使用了,另外還有BiFunction接口,其和Function接口的區別就是apply方法有兩個參數(我的的淺顯理解),還能夠本身定義符合本身業務須要的函數接口,具體定義方法,參考上述兩者便可。
在JDK8中,不少源代碼都用上了函數式編程,有興趣的話,能夠閱讀下相關源碼(推薦Map.java)。