学习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)。