JDK8学习笔记-Function接口

陌路散爱 提交于 2020-04-09 11:11:21

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!