学习JDK8新特性,必不可少的就是函数式编程,那也就不得不了解Function接口的使用了。
首先看下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);
// 省略其他方法
}
接口定义了两个泛型,在使用的时候需要指定。
该接口中比较重要的就是这个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)。
好的,我们来看看如何使用这个方法
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);
上面方法的输出结果如下:
map1 = {1=[1, 1, 1, 1], 2=[2, 2, 2], 3=[3, 3], 4=[4]}
说明下这段代码
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)。
来源:oschina
链接:https://my.oschina.net/u/1158633/blog/1552797