本文带你快速、详细的了解java8的核心四大接口之一的Function接口,从源码到demo了解此接口,让你享受它的妙处。
java8出现了四大接口:消费型,供给型,函数式,断言式
其中Function接口有四个方法:以下依依介绍:
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
(1)apply:
创建一个函数式接口,你需要制订两个泛型参数(姑且这么叫吧)。第一个泛型参数是apply传入的参数类型,第二个是返回参数类型。
你创建了一个Function实现类(用的匿名内部内):你可以通过调用函数的apply来使用该函数。
//Function f= (Function<String, String>) s -> "我想说"+s; lambda表达式
Function f=new Function<String, String>() {
@Override
public String apply(String s) {
return "我想说"+s;
}
};
String res=(String) f.apply("lbwnb");
System.out.println(res);
(2)compose:
你看了源码就知道这玩意儿也是返回一个Function:那这玩意儿有啥用呢:
它允许接受一个Function,返回一个新的Function,他源码也是用的lambda表达式,基础薄弱的同学可能看不懂,我就重新写一下(我写的看不懂也是正常的,只是让你们知道个流程):
Function f1=new Function<Integer, Integer>() {
@Override
public Integer apply(Integer n) {
return n+1;
}
@Override
public <V> Function<V, Integer> compose(Function<? super V, ? extends Integer> before) {
Function<Integer,Integer> that=this; //保存this的指向
return new Function<V, Integer>() {
@Override
public Integer apply(V v) {
Integer tmp=before.apply(v); //传入函数先调用
return that.apply(tmp); //返回外部this调用的apply的值
}
};
}
};
然后我们就可以开始我们的使用流程
Function f1=new Function<Integer, Integer>() {
@Override
public Integer apply(Integer n) {
return n+1;
}
};
Function f2=new Function<Integer, Integer>() {
@Override
public Integer apply(Integer n) {
return n*n;
}
};
//先执将2的值传f2的方法执行完过后,再将返回值作为f1的apply参数
//所以先是2*2=4 再4+1=5
Integer res=(Integer) f1.compose(f2).apply(2);
System.out.println(res);
使用这个函数就可以嵌套的控制函数的执行顺序,举个简单的例子(可能不完全恰当哈):a操作依赖于b,b依赖于c,c依赖于d,所以你调用函数的顺序是d,c,b,a。这样有个啥子问题呢,你这样代码量少还好,要是逻辑啥的强了,代码多了,你就不能很好的确定他们的调用顺序了,使用函数式接口,就做到了一个串联,环环相扣,所有的执行操作,中间产生的数据都不会暴露给外部,外部无法修改,读取(也算是保证了数据流的安全)。我们只管调用。你无需还要中间变量进行接受,并且你不能保证中间产生的数据是否会被修改。这只是衍生出的一小部分使用而已。
(3)andThen
这个方法于上一个相反,是先调用this指向的apply,再将返回值给传入的函数实现类的apply
Function f1=new Function<Integer, Integer>() {
@Override
public Integer apply(Integer n) {
return n + 1;
}
};
Function f2=new Function<Integer, Integer>() {
@Override
public Integer apply(Integer n) {
return n*n;
}
};
Integer res=(Integer) f1.andThen(f2).apply(2);
System.out.println(res);
res的值显然就是9, 2+1=3;3*3=9
调用顺序而已
(4)identify
最后这个是一个静态方法,它也是返回一个Function函数,这个函数的默认实现 你看源码就知道它是直接返回你传入的那个值,就是默认apply实现:t->t 这样;有啥大用我不知道,但它确实可以快速生成一个Function实现类,用于你需要一个Function实现类,而你不想它有啥操作,直接返回原来的值就行。
//1
System.out.println(Function.<Integer>identity().apply(1));
这是本人学习java4个月以来第一篇博客,要是喜欢就关注一下,我有时间会持续更新的~
有错欢迎指正,有需要讲解的可以评论告诉我,说不定下一次我就更新了。