函数式接口
一. 函数式接口简介
什么是函数式接口?
在接口中,有且只有一个抽象方法,那么这个接口就是函数式接口。函数式接口是Lambda表达式使用的前提条件。
为什么要使用函数式接口?
在Java中不支持将函数作为一个数据,也就不能将函数作为方法的参数进行传递。因此给函数外加一层接口的声明,相当于为其穿上一件漂亮的外衣包装起来,如果需要将函数作为方法传递时,就可以传递函数所在接口的实现类对象,来间接的传递方法内容了。
函数式接口定义
使用@FunctionalInterface注解来检查一个接口是否是一个函数式接口。放在接口定义的上方,如果接口是函数式接口,编译通过;如果不是,则编译失败。
二. 函数式接口案例
接下来我们就通过一些代码案例,来带大家学习函数式接口的使用。
2.1 定义函数式接口
这里我们先定义一个带有一个方法的接口。
@FunctionalInterface
public interface MyFunctionInterface {
void show();
}
2.2 使用函数式接口
public class UserFunctionInterface {
//定义一个方法以函数式接口作参数
public static void test(MyFunctionInterface myfun){
myfun.show();
}
//程序入口
public static void main(String[] args) {
//1.使用匿名内部类的方式
MyFunctionInterface myfun = new MyFunctionInterface() {
@Override
public void show() {
System.out.println("使用匿名内部类的方式实现函数式接口....");
}
};
test(myfun);
//2.直接传递匿名内部类
test(new MyFunctionInterface() {
@Override
public void show() {
System.out.println("使用直接传递匿名内部类的方式....");
}
});
//3.使用Lambda表达式的方式使用函数式接口
test(()-> System.out.println("使用Lambda表达式的方式使用函数式接口..."));
}
}
三. 常用函数式接口
Java8中提供了一些常用的函数式接口,在使用类似功能的时候,不需要额外定义接口,直接使用jdk8中提供的即可。
消费型接口
内部包含一个void accept(T t)方法,是一个有参无返回值的方法。其消费数据的数据类型由泛型决定。我们可以定义一个方法,体现不同客户对X元现金的不同消费情况进行描述,即将消费金额和消费方式都以方法参数的形式进行传递。具体需求如下:
1). 客户1: 花了X元, 买了一盒化妆品;
2). 客户2 : 花了X元, 吃了一顿美食。
public class TestConsumer {
//定义方法实现用户消费的功能
public static void userConsumer(Double money,Consumercon){
con.accept(money);
}
//测试
public static void main(String[] args) {
//客户1:花了X元, 买了一盒化妆品
userConsumer(500.0,money -> System.out.println("客户1花了"+money+"买了一盒化妆品"));
//客户2:花了X元, 吃了一顿美食
userConsumer(800.0,money -> System.out.println("客户2花了"+money+"元钱吃了一顿美食"));
}
}
供给型接口
内部包含一个T get()方法,是一个无参有返回值的方法。根据用户指定的接口泛型类型,生产泛型类型的数据提供给我们。
我们再来定义一个方法,能给客户返回一个ArrayList类型的集合,集合中返回几个数据,以及数据有什么规律都由客户决定。具体需求如下:
1). 客户1 : 要5个1-10之间的随机数整数;
2). 客户2 : 要8个1-100之间的偶数。
public class TestSupplier {
public static void main(String[] args) {
//1.客户1 : 要5个1-10之间的随机数整数
Listlist1 = useSupplier(5, new Supplier() {
@Override
public Integer get() {
return (int) (Math.random() * 10 + 1);
}
});
System.out.println(list1);
//2.客户2 : 要8个1-100之间的偶数
Listlist2 = useSupplier(8, () -> {
int num = (int) (Math.random() * 100 + 1);
if (num % 2 == 0) {
return num;
} else {
return num + 1;
}
});
System.out.println(list2);
}
/*
* 根据客户需求,返回n个满足某个规律的数
* */
public static ListuseSupplier(int count, Suppliersup){
Listlist = new ArrayList<>();
for (int i = 0; i < count; i++) {
Integer integer = sup.get();
list.add(integer);
}
return list;
}
}
函数型接口
内部包含一个R apply(T t)方法,是一个有参有返回值的方法。通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值。这里我们也可以定义一个方法,给定一个整数x,根据Lambda表达式的实现转换成对应的y,具体需求如下:
1). 客户1 : y为x的2倍;
2). 客户3 : y为x的平方。
public class TestFunction {
public static void main(String[] args) {
// 1)客户1 : y为x的2倍
System.out.println(useFunction(5, x -> x * 2));// 10
// 2) 客户2 : y为x的平方
System.out.println(useFunction(-9, x -> x * x));// 81
}
/*
* 根据x计算y
* 参数x代表用户传递的数
* 参数2代表用户要求得到结果的实现方式
* */
public static int useFunction(int x, Function<integer, integer=""> fun) {
return fun.apply(x);
}
}
断言型接口
内部包含一个boolean test(T t)方法,对给定的参数进行判断(判断逻辑由Lambda表达式实现),如果符合要求返回true,不符合则返回false。
这里也定义一个方法,需要用户提供一个容器ArrayList,根据用户的需求,将容器中符合条件的数据筛选出来,将筛选出的数据放置在新容器中返回给用户。具体需求如下:
1). 客户1: 要求返回集合中能被2整除的所有数;
2). 客户2: 要求返回不大于100所有的数据。
public class TestPredicate {
public static void main(String[] args) {
ArrayListlist1 = new ArrayList<>();
list1.add(12);
list1.add(11);
list1.add(120);
list1.add(111);
list1.add(67);
list1.add(88);
// 1)客户1 : 要求容器中的所有数, 都能被2整除
System.out.println(usePredicate(list1,x->x%2==0));// [12, 120, 88]
// 2)客户2 : 要求所有的数据都不大于100
System.out.println(usePredicate(list1,x->x < 100));// [12, 11, 67, 88]
}
/*
* 对客户提交的数据进行过滤处理
* */
public static ArrayListusePredicate(ArrayListlist1, Predicatepre){
ArrayListlist = new ArrayList<>();
for(Integer i : list1){
//过滤处理,符合条件的数据放到新集合中
if(pre.test(i)){
list.add(i);
}
}
//返回新集合
return list;
}
}
现在你学会函数式接口了吗?

相关推荐HOT
更多>>
怎么将string字符串转换成byte[]数组?
例如,使用默认字符集转换可以如下所示: 也可以指定字符集: 这将使用UTF-8字符集将字符串转换成字节数组。详情>>
2023-04-25 17:14:58
如何禁用浏览器的前进和后退功能
URL) 本质就是在进入页面或者路由跳转的时候在历史记录中保存一条没有意义的记录,这样用户在点击前后后退按钮的时候就没有效果。详情>>
2023-04-19 10:36:58
react传值是什么意思?
react是组件化的框架,组件实例间作用域是互相隔离的,所以组件间的通信就变成了开发过程中常常要解决的问题,根据场景可以分为: 父子组...详情>>
2023-04-18 17:23:22
使用IE浏览器遇见过哪些兼容问题?
在IE6中,块元素设置float并且有水平方向的margin时,margin显示出来会比设置的值大,会导致最后一块元素被顶到下面去; 解决办法:在CSS文...详情>>
2023-04-12 09:21:12