函数式接口不会用?看这篇文章就够了

╰半橙微兮° 2024-03-31 16:41 206阅读 0赞

一. 函数式接口简介

最近有粉丝给壹哥发来私信,说工作中要用到函数式接口,但是自己却不知道怎么用。既然如此,壹哥就给大家编写一个入门级别的函数式接口教程吧,希望可以让大家对函数式编程快速入门。

1. 什么是函数式接口?

如果在Java的接口中,有且只有一个抽象方法,那么这种接口就是函数式接口。函数式接口是使用Lambda表达式的前提条件。

2. 为什么要使用函数式接口?

在Java中不支持将函数作为一个数据,也就不能将函数作为方法的参数进行传递。因此给函数外加一层接口的声明,相当于为其穿上一件漂亮的外衣包装起来。如果需要将函数作为方法传递时,就可以传递函数所在接口的实现类对象,来间接的传递方法内容了。

3. 函数式接口定义

我们可以使用@FunctionalInterface注解来检查一个接口是否是一个函数式接口。放在接口定义的上方,如果接口是函数式接口,编译通过;如果不是,则编译失败。

二. 函数式接口案例

接下来壹哥就通过一些代码案例,来带大家学习函数式接口的使用。

1. 定义函数式接口

这里我们先定义一个带有一个方法的接口。

  1. @FunctionalInterface
  2. public interface MyFunctionInterface {
  3. void show();
  4. }

2. 使用函数式接口

然后我们再编写一个测试类进行测试。

  1. public class UserFunctionInterface {
  2. //定义一个方法以函数式接口作参数
  3. public static void test(MyFunctionInterface myfun){
  4. myfun.show();
  5. }
  6. //程序入口
  7. public static void main(String[] args) {
  8. //1.使用匿名内部类的方式
  9. MyFunctionInterface myfun = new MyFunctionInterface() {
  10. @Override
  11. public void show() {
  12. System.out.println("使用匿名内部类的方式实现函数式接口....");
  13. }
  14. };
  15. test(myfun);
  16. //2.直接传递匿名内部类
  17. test(new MyFunctionInterface() {
  18. @Override
  19. public void show() {
  20. System.out.println("使用直接传递匿名内部类的方式....");
  21. }
  22. });
  23. //3.使用Lambda表达式的方式使用函数式接口
  24. test(()-> System.out.println("使用Lambda表达式的方式使用函数式接口..."));
  25. }
  26. }

三. 常用函数式接口

Java8中提供了一些常用的函数式接口,在使用类似功能的时候,不需要额外定义接口,直接使用jdk8中提供的即可。

1. 消费型接口

消费型接口的内部包含了一个void accept(T t)方法,是一个有参无返回值的方法,其消费数据的数据类型由泛型决定。我们可以定义一个方法,体现不同客户对X元现金的不同消费情况进行描述,即将消费金额和消费方式都以方法参数的形式进行传递。具体需求如下:

1). 客户1: 花了X元, 买了一盒化妆品;

2). 客户2 : 花了X元, 吃了一顿美食。

  1. public class TestConsumer {
  2. //定义方法实现用户消费的功能
  3. public static void userConsumer(Double money,Consumer<Double> con){
  4. con.accept(money);
  5. }
  6. //测试
  7. public static void main(String[] args) {
  8. //客户1:花了X元, 买了一盒化妆品
  9. userConsumer(500.0,money -> System.out.println("客户1花了"+money+"买了一盒化妆品"));
  10. //客户2:花了X元, 吃了一顿美食
  11. userConsumer(800.0,money -> System.out.println("客户2花了"+money+"元钱吃了一顿美食"));
  12. }
  13. }

2. 供给型接口

供给型接口的内部包含了一个T get()方法,是一个无参有返回值的方法。根据用户指定的接口泛型类型,生产泛型类型的数据提供给我们。

我们再来定义一个方法,能给客户返回一个ArrayList类型的集合,集合中返回几个数据,以及数据有什么规律都由客户决定。具体需求如下:

1). 客户1 : 要5个1-10之间的随机数整数;

2). 客户2 : 要8个1-100之间的偶数。

  1. public class TestSupplier {
  2. public static void main(String[] args) {
  3. //1.客户1 : 要5个1-10之间的随机数整数
  4. List<Integer> list1 = useSupplier(5, new Supplier<Integer>() {
  5. @Override
  6. public Integer get() {
  7. return (int) (Math.random() * 10 + 1);
  8. }
  9. });
  10. System.out.println(list1);
  11. //2.客户2 : 要8个1-100之间的偶数
  12. List<Integer> list2 = useSupplier(8, () -> {
  13. int num = (int) (Math.random() * 100 + 1);
  14. if (num % 2 == 0) {
  15. return num;
  16. } else {
  17. return num + 1;
  18. }
  19. });
  20. System.out.println(list2);
  21. }
  22. /*
  23. * 根据客户需求,返回n个满足某个规律的数
  24. * */
  25. public static List<Integer> useSupplier(int count, Supplier<Integer> sup){
  26. List<Integer> list = new ArrayList<>();
  27. for (int i = 0; i < count; i++) {
  28. Integer integer = sup.get();
  29. list.add(integer);
  30. }
  31. return list;
  32. }
  33. }

3. 函数型接口

函数型接口的内部包含了一个R apply(T t)方法,是一个有参有返回值的方法。通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值。这里我们也可以定义一个方法,给定一个整数x,根据Lambda表达式的实现转换成对应的y,具体需求如下:

1). 客户1 : y为x的2倍;

2). 客户3 : y为x的平方。

  1. public class TestFunction {
  2. public static void main(String[] args) {
  3. // 1)客户1 : y为x的2倍
  4. System.out.println(useFunction(5, x -> x * 2));// 10
  5. // 2) 客户2 : y为x的平方
  6. System.out.println(useFunction(-9, x -> x * x));// 81
  7. }
  8. /*
  9. * 根据x计算y
  10. * 参数x代表用户传递的数
  11. * 参数2代表用户要求得到结果的实现方式
  12. * */
  13. public static int useFunction(int x, Function<Integer, Integer> fun) {
  14. return fun.apply(x);
  15. }
  16. }

4. 断言型接口

断言型接口的内部包含了一个boolean test(T t)方法,对给定的参数进行判断(判断逻辑由Lambda表达式实现),如果符合要求返回true,不符合则返回false。

这里也定义一个方法,需要用户提供一个容器ArrayList,根据用户的需求,将容器中符合条件的数据筛选出来,将筛选出的数据放置在新容器中返回给用户。具体需求如下:

1). 客户1: 要求返回集合中能被2整除的所有数;

2). 客户2: 要求返回不大于100所有的数据。

  1. public class TestPredicate {
  2. public static void main(String[] args) {
  3. ArrayList<Integer> list1 = new ArrayList<>();
  4. list1.add(12);
  5. list1.add(11);
  6. list1.add(120);
  7. list1.add(111);
  8. list1.add(67);
  9. list1.add(88);
  10. // 1)客户1 : 要求容器中的所有数, 都能被2整除
  11. System.out.println(usePredicate(list1,x->x%2==0));// [12, 120, 88]
  12. // 2)客户2 : 要求所有的数据都不大于100
  13. System.out.println(usePredicate(list1,x->x < 100));// [12, 11, 67, 88]
  14. }
  15. /*
  16. * 对客户提交的数据进行过滤处理
  17. * */
  18. public static ArrayList<Integer> usePredicate(ArrayList<Integer> list1, Predicate<Integer> pre){
  19. ArrayList<Integer> list = new ArrayList<>();
  20. for(Integer i : list1){
  21. //过滤处理,符合条件的数据放到新集合中
  22. if(pre.test(i)){
  23. list.add(i);
  24. }
  25. }
  26. //返回新集合
  27. return list;
  28. }
  29. }

现在你学会函数式接口了吗?如果你还有什么疑问,在评论区留言或私信吧。

发表评论

表情:
评论列表 (有 0 条评论,206人围观)

还没有评论,来说两句吧...

相关阅读