简介
为了更好的将函数作为参数,Java遂引入了Function接口
Function<T, R>的使用
看其源码
要素察觉
- 该接口会接收一个参数,且会产生结果
- 在使用这个接口前需要明确定义参数类型和返回的结果类型(Java的泛型就是这么回事)
- 里面有一个
apply
方法将会对参数进行操作,并返回结果 - 因为是函数式接口(
@FunctionalInterface
),可以通过lambda表达式实现该接口
测试
public class FunctionTest {
public static void main(String[] args) {
FunctionTest test = new FunctionTest();
//lambda表达式实现了apply,也就实现了Function接口,不要被<Integer, Integer>影响了
System.out.println(test.operate(5, integer -> integer * integer));//第二个参数是方法
} //输入参数的类型//返回类型
public int operate(int i, Function<Integer, Integer> function){
return function.apply(i);//apply的返回值是Integer,参数是i
}
}
复制代码
Function<T, R>
进阶玩法,使用Function的默认方法compose
和andThen
再观察一波Function<T, R>接口源码
要素察觉
- 两个方法都使用了两次
apply
,只是this.apply
执行的先后不同 - 说明两个
Function
可以组合起来用 => 两个apply
可以组合使用 => 可以用两个Lambda表达式实现apply
测试
public class FunctionTest {
public static void main(String[] args) {
FunctionTest test = new FunctionTest();
System.out.println(test.operate1(2,integer -> integer*3,integer -> integer*integer));
System.out.println("-----------------------");
System.out.println(test.operate2(2,integer -> integer*3,integer -> integer*integer));
}
public int operate1(int i,Function<Integer, Integer> function1 ,Function<Integer, Integer> function2){
return function1.compose(function2).apply(i);//当前对象(this)为function1
}
public int operate2(int i,Function<Integer, Integer> function1 ,Function<Integer, Integer> function2){
return function1.andThen(function2).apply(i);//当前对象(this)为function1
}
}
复制代码
解释
- compose
执行f1之前(before)先执行f2
- andThen
执行f1之后(after)再执行f2
小结
- 总之,要分清当前function,也就是当前对象,判断执行顺序。对象有方法和成员变量。
- 本例中,function1都是当前对象,调用它的方法,以及将function2作为参数传给它。
- function是对象,只是有函数的功能而已。面向对象不能丢
BiFunction<T,U,R>的使用
看其源码
要素察觉
BiFunction
接收两个参数返回一个结果- 它有一个抽象方法
apply
,接收两个参数 - 它有一个
andThen
的默认方法 - 和
Function
比起来多了一个参数,少了一个compose
方法- 因为
Function
只需要一个参数,BiFunction
刚好可以返回一个参数,可以先BiFuction
再Function
,所以有andThen
方法 BiFunction
是当前对象,如果它后执行,其他Function
先执行,且它们都只会返回一个结果,就会导致BiFunction
只有一个参数,满足不了BiFunction的需要两个参数的需求,所以没有compose
方法
- 因为
测试
public class FunctionTest {
public static void main(String[] args) {
FunctionTest test = new FunctionTest();
System.out.println(test.operate3(2,3, (a,b) -> a-b));
System.out.println("-----------------------");
System.out.println(test.operate4(3,4,(a,b) -> a*b, result -> result*10));
} //指定参数类型和返回类型
public int operate3(int a, int b, BiFunction<Integer,Integer,Integer> function){
return function.apply(a,b);
}
public int operate4(int a, int b, BiFunction<Integer,Integer,Integer> function1,Function<Integer, Integer> function2){
return function1.andThen(function2).apply(a,b);//andThen的参数是Function
}
}
复制代码
解释
其实
Bifuntction
和Function
差不多,BiFunction
接收两个参数,Function
接收一个参数
最后
这两个接口有啥用?
- 当需要对数据进行操作时且你想用lambda表达式时,就可以用它,而不需要自己去写一个满足函数式接口的接口。
- 而且对一个或两个数据的修改和操作是不同的,比如两个数的加减乘除,就不需要定义四个方法,只要Bifunction接口,用不同的Lambda表达式实现就好了
- 某个操作只用一次用Lamdba表达式即可,就不需要单独封装成方法了
System.out.println(test.operate3(2,3, (a,b) -> a+b));// 只用一次,就不需要封装成说明add方法之类的
System.out.println(test.operate3(2,3, (a,b) -> a-b));
System.out.println(test.operate3(2,3, (a,b) -> a*b));
System.out.println(test.operate3(2,3, (a,b) -> a/b));// 只用一次,就不需要封装成说明div方法之类的
public int operate3(int a, int b, BiFunction<Integer,Integer,Integer> function){
return function.apply(a,b);
}
复制代码
- 如果你一个方法都不想封装,可以这么写
public class FunctionTest {
public static void main(String[] args) {
Function<Integer, Integer> function;//省去一堆基本数据类型的变量定义了
function = a ->a*3;
System.out.println(function.apply(2));
}
}
复制代码
另外一个小样例,对集合进行操作
- People
public class People {
String name;
int age;
//getter和setter,自行添加
public People(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
复制代码
- 需求:获取People集合中年龄小于特定的元素
public class FunctionTestPro {
public static void main(String[] args) {
FunctionTestPro testPro = new FunctionTestPro();
People p1 = new People("jetty",18);
People p2 = new People("kitty",12);
People p3 = new People("Matty",70);
List<People> list = Arrays.asList(p1,p2,p3);
//获取年龄小于70的元素
List<People> list1 = testPro.getPeople(70,list,(age,peopleList) ->peopleList.stream()//形成流
.filter(people -> people.getAge()< age ) //获取小于age的元素
.collect(Collectors.toList()));//将结果累积到List中,并返回
list1.forEach(System.out::println);//输出
//是数字码的,请重写People的toString方法
} //条件 需要被操作的集合 // 条件age为Integer 被操作的对象为List 返回值为List
public List<People> getPeople(int age, List<People> peopleList ,BiFunction<Integer,List<People>,List<People>> function){
return function.apply(age,peopleList);//两个参数
}
}
复制代码
- Stream流,将对象以流水的形态通过各种方法过滤,得到所需结果
- 对于Lambda表达式,如果方法体只有一行,不需要
{}
也不需要return
,它会自动return
,如果需要return
的话。- 如果多行请用
{}
和return
(a, b) ->{ a=a*b; return a+b; }
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END