首页 > 编程语言 >Java函数式接口再理解

Java函数式接口再理解

时间:2023-11-30 20:36:59浏览次数:40  
标签:Predicate Java 函数 型函数 int 接口 public

Java函数式接口再理解


前言

这篇文章主要是我个人对函数式接口的再理解,若有理解偏差或考虑不周的地方,欢迎批评指出,共同进步!

这里做下记录,以便日后遗忘查阅;


目录

目录


一、什么是函数式接口

① 概述

我们都知道接口的作用是定义一组抽象规范,供实现类进行实际实现。只要类实现了该接口,都要实现其中的抽象方法。

在Java8之后接口中不仅可以定义抽象方法,还可以定义非抽象方法。

因此,只存在一个抽象方法的接口,我们称之为函数式接口。

在JDK中提供的函数式接口都加上了@FunctionalInterface注解进行标识,但是无论是否加上该注解只要接口中只有一个抽象方法,都是函数式接口。

注意:如果一个接口本身不存在抽象方法,其继承了父接口是一个函数式接口,其也是一个函数式接口。

② 一个标准的函数式接口

image-20231130141137487

③ 举例感受函数式接口的作用

import java.util.function.IntBinaryOperator;

public class Main {
    public static void main(String[] args) {
        // 实际逻辑为加操作时,如下实现
        var jiaResult = test(new IntBinaryOperator() {
            @Override
            public int applyAsInt(int left, int right) {
                return left + right;
            }
        });
        System.out.println("jiaResult:" + jiaResult);

        // 实际逻辑为减操作时,如下实现
        var jianResult = test(new IntBinaryOperator() {
            @Override
            public int applyAsInt(int left, int right) {
                return left - right;
            }
        });
        System.out.println("jianResult:" + jianResult);
        // ...或者任何其他操作。
    }

    public static int test(IntBinaryOperator operator) {
        /*
         * 该方法在此之前的逻辑操作
         * */
        // 假设不管通过什么手段我们最终得到了两个int类型的值
        int a = 1;
        int b = 2;
        // 中间部分逻辑我们还不确定或者逻辑是动态的,但我们知道不管中间逻辑怎么动态的变化,我们最终要的是一个int类型的数据。
        // 那么我们就可以在函数式接口里面去找一个,入参是两个int类型,出参是一个int类型的函数式接口,来进行抽象处理。
        // 在具体调用的时候再去写这部分的逻辑实现。是加-减-乘-除或其他都根据业务需要进行代码实现。
        int result = operator.applyAsInt(a, b);
        /*
         * 得到这个int类型的数据之后做一堆后续操作
         * */
        return result;
    }
}

④ 控制台打印结果

jiaResult:3
jianResult:-1

⑤ 补充:@FunctionalInterface注解作用

其实在上面我们已经知道了JDK自定义的函数式接口都会加上这个注解。如果不加,但是接口中只有一个抽象方法,其也是一个函数式接口。其实@FunctionalInterface注解就是为了验证该接口是不是一个函数式接口,这一点可以类比@Override注解理解。

下面我们自定义一个函数试接口来演示一下@FunctionalInterface注解的作用:

1. 标准函数式接口

image-20231130151253976

2. 非标志函数式接口

image-20231130151419135

可以看到,当不满足函数式接口规则时,添加该注解会有报错提示。

二、常见函数式接口及常见说法说明

① 消费型函数式接口

1. 什么是消费型函数式接口

所谓消费型函数式接口,其实就是只进不出型。例如如下JDK1.8提供的Consumer函数式接口,只接受任意类型的入参,但没有返回值。这种消费数据的接口,一般称为消费型函数式接口。

2.举例:Consumer

image-20231130152825015

② 计算转换型函数式接口

1. 什么是计算转换型函数式接口

所谓计算转换型函数式接口,其实就是有进有出型。例如如下JDK1.8提供的Function函数式接口,接受任意类型的入参,返回任意类型的出参。这种转换数据的接口,一般称为计算转换型函数式接口。

2.举例:Function

image-20231130153610536

③ 判断型函数式接口

1. 什么是判断型函数式接口

所谓判断型函数式接口,其实就是有入参其返回boolean型。例如如下JDK1.8提供的Predicate函数式接口,接受任意类型的入参,返回boolean类型出参。这种断言数据的接口,一般称为判断型函数式接口。

2.举例:Predicate

image-20231130154047453

④ 生产型函数式接口

1. 什么是生产型函数式接口

所谓生产型函数式接口,其实就是无入有出型。例如如下JDK1.8提供的Supplier函数式接口,不接受入参,返回任意类型的出参。这种生产数据的接口,一般称为生产型函数式接口。

2.举例:Supplier

image-20231130154832639

三、通过函数式接口常用默认方法学习植入链式编程思想

从上述学习中,我们了解到函数式接口的一些基本作用和用法。我们也知道JDK1.8之后接口中也可以定义默认方法,部分函数式接口会定义一些默认方法供使用。我们接下来来学习该如何使用这些默认方法。

接下来我将使用判断型函数式接口Predicate来进行学习举例。

① 引入stream.filter

我们知道,Java-stream流中实现的filter方法需要一个Predicate函数式接口的实现类来指定过滤数据条件。所以在使用时我们需要创建匿名实现类,来实现该函数式接口方法。

image-20231130192636669

② 使用stream.filter

创建匿名实现类,实现函数式接口方法。

    public static void main(String[] args) {
        var result = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).filter(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer > 2;
            }
        }).toList();
        System.out.println(result);
    }

运行结果:

[3, 4, 5, 6, 7, 8, 9]

可以看出我们进行了一次数据过滤。

③ 使用Predicate的默认方法and二次过滤数据

根据如下默认and方法我们可以看到,其入参和返回值都是Predicate类型。

image-20231130193649574

于是我们就可以通过Predicate匿名实现类来调用默认and方法,再次传入Predicate匿名实现类,因为默认and方法的返回值仍是Predicate的匿名实现类,所以我们仍然可以继续链式调用Predicate匿名实现类中的默认方法。通过这个例子我想你应该可以对链式编程有一个初步的了解。

代码如下:

    public static void main(String[] args) {
        var result = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).filter(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer > 2;
            }
        }.and(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer < 7;
            }
        })).toList();
        System.out.println(result);
    }

运行结果:

[3, 4, 5, 6]

其实到这里,如果学过lambda表达式写法的同学,可以去尝试简化一下上述代码案例。

其实实际上你会发现,调用函数式接口默认方法的时候,只能使用匿名实现类来进行操作,所以一般我们不这样去进行实际开发,只有你自己想要去自定义一些函数式编程的一些方法时才回去使用。

我这里举例的重点是理解一下链式编程思想。

标签:Predicate,Java,函数,型函数,int,接口,public
From: https://www.cnblogs.com/zhao-XH/p/17868170.html

相关文章

  • java接入百度翻译接口简单实现中译英
    1.去官网开通标准版https://api.fanyi.baidu.com/access/0/1百度翻译开放平台(baidu.com)开通成功后,点击立即使用后的页面是这样子的  将APPID和密钥复制下来,待会连接需要使用到  2.下载java包百度翻译开放平台(baidu.com) 下载后,复制粘贴到自己的项目中......
  • 在eclipse中拖动项目到Tomcat服务器中报错:Project facet Java version 16 is not supp
    ......
  • java使用hive-jdbc查询超时:java.sql.SQLException: org.apache.thrift.transport.TTra
     java.sql.SQLException:org.apache.thrift.transport.TTransportException:java.net.SocketTimeoutException:Readtimedout  atorg.apache.hive.jdbc.HiveStatement.execute(HiveStatement.java:262)  atorg.apache.hive.jdbc.HivePreparedStatement.execute(......
  • Java常用库介绍
    ApacheCommons与Guava 参考资料:开源工具导航——ApacheCommons与Guava全览https://blog.csdn.net/qq_35946969/article/details/123418026Java开源工具库使用之Apachecommons-lang3https://blog.csdn.net/qq_23091073/article/details/126743040 ......
  • 三角函数计算器
    一个简单的三角函数计算器#include<iostream>#include<cstdlib>#include<iomanip>#include<cmath>constexprautoPI=M_PI;intmenu_select(){intselect;std::cout<<"-------WelcometoSnowCalculator-------"<......
  • mysql 常用函数
    DATE_SUB(CURRENT_DATE,INTERVAL7day)DATE_add(CURRENT_DATE,INTERVAL7day)不能通过orderby加groupby取最新的一条。只有通过两个表连接才能实现。同时去掉空格和空whereISNULL(name)=0andLENGTH(trim(name))>0,ltrim和rtrimsubstring_index(“待截取有用部分的......
  • Shell封装日志函数
       使用echo打印输出日志严重影响观瞻,想打印时间戳就得每次都得把date命令加上,想自动加点别的东西真是好麻烦,封装一个日志函数,方便脚本在运行的时候输出日志,超级方便1、简单定义一个log函数function_log(){echo-e"${@}"}_log"helo"用的时候直接把想打印的信......
  • 大事件接口文档
    大事件接口文档大事件接口文档-V1.01.用户相关接口1.1注册1.1.1基本信息请求路径:/user/register请求方式:POST接口描述:该接口用于注册新用户1.1.2请求参数请求参数格式:x-www-form-urlencoded请求参数说明:参数名称说明类型是否必须备注username用户名......
  • 欧拉函数模板
    #include<bits/stdc++.h>usingnamespacestd;//欧拉函数,质数vector<int>euler_range(intn){vector<int>phi(n+1),prime;vector<bool>is_prime(n+1,true);is_prime[1]=0,phi[1]=1;for(inti=2;i<=n;i......
  • 学习笔记2:JavaSE & API(流处理)
    1、File:java.io.File(1)定义:File类的每一个实例可以表示硬盘(文件系统)中的一个文件或目录(实际上表示的是一个抽象路径)(2)功能:访问其表示的文件或目录的属性信息,例如:名字,大小,修改时间等等创建和删除文件或目录访问一个目录中的子项(3)构造器:​File(Stringpathname)​......