java 函数式编程(java自定义函数)

以前写过一篇java8的流操作,人们都说流操作是函数式编程,但函数式编程是什么呢?什么是函数式编程什么是函数式编程?它是一种编程范式,即一切都是数学函数。函数式编程语言里也可以有对象,但通常这些对象都是恒定不变的——要么是函数参数,要什么是函数返回值。函数式编程语言里没有for/next循环,因为这些逻辑意味着有状态的改变。相替代的是,这种循环逻辑在函数式编程语言里是通过递归、把函…

大家好,又见面了,我是你们的朋友全栈君。

以前写过一篇java8的流操作,人们都说流操作是函数式编程,但函数式编程是什么呢?

什么是函数式编程

什么是函数式编程?它是一种编程范式,即一切都是数学函数。函数式编程语言里也可以有对象,但通常这些对象都是恒定不变的 —— 要么是函数参数,要什么是函数返回值。函数式编程语言里没有 for/next 循环,因为这些逻辑意味着有状态的改变。相替代的是,这种循环逻辑在函数式编程语言里是通过递归、把函数当成参数传递的方式实现的。

函数式编程单看上面的理论无疑是无法理解的,所以,需要通过它的一些特点来感受什么是函数式编程

函数是”第一等公民”

所谓 第一等公民(first class),指的是函数与其他数据类型一样,处于平等地位, 可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。 举例来说,下面代码中的print变量就是一个函数,可以作为另一个函数的参数。

只用”表达式”,不用”语句”

“表达式”(expression)是一个单纯的运算过程,总是有返回值;”语句”(statement)是执行某种操作,没有返回值。函数式编程要求,只使用表达式,不使用语句。也就是说, 每一步都是单纯的运算,而且都有返回值。

原因是 函数式编程的开发动机,一开始就是为了处理运算(computation),不考虑系统的读写(I/O)。 “语句”属于对系统的读写操作,所以就被排斥在外。

当然,实际应用中,不做I/O是不可能的。因此,编程过程中,函数式编程只要求把I/O限制到最小,不要有不必要的读写行为,保持计算过程的单纯性。

没有”副作用”

所谓副作用(side effect),指的是函数内部与外部互动(最典型的情况,就是修改全局变量的值),产生运算以外的其他结果。

函数式编程强调没有”副作用”,意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为, 尤其是不得修改外部变量的值.有不少朋友问,如何深入学习Java后端技术栈,今天分享一个,互联网牛人整理出来的Java深入学习路线图,以及开发工具包,【戳我进入】学习裙。

不修改状态

上一点已经提到,函数式编程只是返回新的值, 不修改系统变量 。因此,不修改变量,也是它的一个重要特点。

在其他类型的语言中,变量往往用来保存”状态”(state)。不修改变量,意味着状态不能保存在变量中。函数式编程使用参数保存状态,最好的例子就是递归。

引用透明

引用透明(Referential transparency),指的是函数的运行不依赖于外部变量或”状态”,只依赖于输入的参数,任何时候只要参数相同,引用函数所得到的返回值总是相同的。

OO(object oriented,面向对象)是抽象数据,FP(functional programming,函数式编程)是抽象行为。

在java中,函数式编程是通过 lambda表达式 实现的。

lambad表达式

基本表达形式如下:

Runnable noArguments = () -> System.out.println("Hello World");

Lambda 表达式的基本语法是:

->
->
  • 当只用一个参数,可以不需要括号 () 。 然而,这是一个特例。
  • 正常情况使用括号 () 包裹参数。 为了保持一致性,也可以使用括号 () 包裹单个参数,虽然这种情况并不常见。
  • 如果没有参数,则必须使用括号 () 表示空参数列表。
  • 对于多个参数,将参数列表放在括号 () 中。
  • 方法体的语句超过一句时,需要使用 {} ,并根据情况看是否需要 return

Lambda 表达式产生函数,而不是类。 在 JVM(Java Virtual Machine,Java 虚拟机)上,一切都是一个类,因此在幕后执行各种操作使 Lambda 看起来像函数 —— 但作为程序员,你可以高兴地假装它们“只是函数”。

函数接口

/** 强制 javac 检查一个接口是否符合函数接口的标准。如果该注释添加给一个枚举类型、类或另一个注释,或者接口包含不止一个抽象方法,javac 就会报错 **/
@FunctionalInterface //该注解不是必选项
interface Yunzhi {
//只包含一个抽象方法,称为函数式方法。
    String test(String s);
}


public class LambdaExpressions {

    static  Yunzhi yunzhi = x ->"this is  a" +  x ;

    public static void main(String[] args) {
        System.out.println(yunzhi.test("test"));

    }
}

yunzhi 实际上是实现了 Yunzhi 的 test() ,类似上面的这种接口叫函数式接口。

JDK 8 中提供了大量的函数接口,这些接口定义在 java.util.function 中,因此我们一般情况下不需再定义自己的接口,同时,各个接口的作用和名字都是相对应的,所以,了解函数式接口的命名模式就是很有必要的了。

以下是基本命名准则:

  1. 如果只处理对象而非基本类型,名称则为 Function , Consumer , Predicate 等。参数类型通过泛型添加。
  2. 如果接收的参数是基本类型,则由名称的第一部分表示,如 LongConsumer , DoubleFunction , IntPredicate 等,但基本 Supplier 类型例外。
  3. 如果返回值为基本类型,则用 To 表示,如 ToLongFunction <T> 和 IntToLongFunction 。
  4. 如果返回值类型与参数类型一致,则是一个运算符:单个参数使用 UnaryOperator ,两个参数使用 BinaryOperator 。
  5. 如果接收两个参数且返回值为布尔值,则是一个谓词(Predicate)。
  6. 如果接收的两个参数类型不同,则名称中有一个 Bi 。

下表描述了 java.util.function 中的目标类型(包括例外情况):

特征 数式方法名 示例
无参数; 
无返回值
Runnable (java.lang) 
run()
Runnable
无参数; 
返回类型任意
Supplier get() getAs类型()

Supplier <T>

BooleanSupplier

IntSupplier

LongSupplier

DoubleSupplier

无参数; 
返回类型任意
Callable (java.util.concurrent) 
call()
Callable <V>
1 参数; 
无返回值
Consumer accept() Consumer<T>

IntConsumer

LongConsumer

DoubleConsumer

2 参数 Consumer BiConsumer accept() BiConsumer<T,U>
2 参数 Consumer ; 
1 引用; 
1 基本类型
Obj类型Consumer accept() ObjIntConsumer<T>ObjLongConsumer<T> ObjDoubleConsumer<T>
1 参数; 
返回类型不同
Function apply() To类型 和 类型To类型 
applyAs类型()

Function <T,R>

IntFunction <R>

LongFunction<R>

DoubleFunction <R>

ToIntFunction <T>

ToLongFunction<T> ToDoubleFunction<T>

IntToLongFunction

IntToDoubleFunction

LongToIntFunction

LongToDoubleFunction

DoubleToIntFunction

DoubleToLongFunction

1 参数; 
返回类型相同
UnaryOperator apply() UnaryOperator<T>

IntUnaryOperator

LongUnaryOperator

DoubleUnaryOperator

2 参数类型相同; 
返回类型相同
BinaryOperatorapply() BinaryOperator<T>

IntBinaryOperator

LongBinaryOperator

DoubleBinaryOperator

2 参数类型相同; 
返回整型
Comparator 
(java.util) 
compare()
Comparator<T>
2 参数; 
返回布尔型
Predicate test() Predicate<T> BiPredicate<T,U>

IntPredicate

LongPredicate

DoublePredicate

参数基本类型; 
返回基本类型
类型To类型Function applyAs类型()

IntToLongFunction

IntToDoubleFunction

LongToIntFunction

LongToDoubleFunction

DoubleToIntFunction

DoubleToLongFunction

2 参数类型不同 Bi操作 (不同方法名) BiFunction<T,U,R> BiConsumer<T,U> BiPredicate<T,U>ToIntBiFunction<T,U> ToLongBiFunction<T,U> ToDoubleBiFunction<T>

其中最常用的是:

java 函数式编程(java自定义函数)

接下来实际的看看如何使用这些接口

class Foo {}

class Bar {
    Foo f;
    Bar(Foo f) { this.f = f; }
}

public class FunctionVariants {
    static Function<Foo, Bar> f1 = f -> new Bar(f);

    public static void main(String[] args) {
        Bar b = f1.apply(new Foo());
    }
}

学到这里才突然发现,虽然以前完全不知道函数接口这个东西,但实际上却已经在使用他了,比如 Comparator 广泛的运用在各种比较当中, pridect 也在spring的综合查询中使用过了。

关于函数式编程的争议

虽然在宣传中,函数式编程有着巨大的优势,比如适合 并行编程 、 代码可靠性 和 代码创建和库复用 ,但在某些大佬看来:

关于函数式编程能高效创建更健壮的代码这一观点仍存在部分争议。虽然已有一些好的范例,但还不足以证明纯函数式语言就是解决编程问题的最佳方法。

不管怎样,多学一学总是好的

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/126065.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • WinSCP连接被拒绝「建议收藏」

    WinSCP连接被拒绝「建议收藏」之前用WinSCP连接华为云服务器传输文件的时候没有出现过问题,但是现在连接实验室电脑的时候报“网络错误,连接被拒绝”。上网查了一下,发现是实验室服务器没有安装openssh-server,参考博文进行安装:Ubuntu安装sshd服务_我是大魔王2的博客-CSDN博客_ubuntu安装sshd具体安装步骤:1.安装openssh-serversudoapt-getinstallopenssh-server2.检查sshd是否启动一般安装成功后就会启动sshd服务,可以通过.

    2022年9月17日
  • TexturePacker 图片加密

    TexturePacker 图片加密摘自:http://article.ityran.com/archives/3950#jtss-tsinaTexturePacker最新版本中增加了一个新功能以防止你的产品资源被反编译出来。它被称为ContentProtection,即图片加密。你的app或者游戏仍可以解密数据,但是其他人则需要耗上很长的时间才能够完成激活成功教程。理论上别人仍可能从源码提取出密钥,并写出一些解码器,这是因为解

    2022年6月21日
  • SourceTree Gitflow 使用一 (Git项目转Gitflow)

    SourceTree Gitflow 使用一 (Git项目转Gitflow)1.克隆项目到本地2.SourceTree打开克隆的项目3点击master点击右上角git工作流

    2022年11月2日
  • mse均方误差例题_误差函数计算器

    mse均方误差例题_误差函数计算器文章目录背景函数代码调用方法调用测试函数背景本人最近需要写多个仿真,需要大量用到MSE(均方误差)计算,于是干脆将MSE运算封装为函数,后续使用直接进行调用即可。函数代码%Project:均方误差函数%Author:Jace%Data:2021/11/01%====================函数体====================function[MSE]=MSE(Dim,Step,N,xkf,x)%====================分配空间=======

    2022年9月30日
  • 系统测试计划_软件系统测试计划

    系统测试计划_软件系统测试计划系统测试是针对软件产品系统进行的测试(黑盒测试) 功能测试:是否符合需求规格、功能设计、用户满意度 非功能测试:容错性、稳定性、异常处理能力、高强度输入处理能力、可用性、性能 系统测试(系统测试计划包含系统测试的设计、实现和执行的工作): 系统测试计划:完成系统测试计划。软件产品的需求规格确定后编写。 系统测试设计:完成系统方案。软件概要设计文档确定后编写。 系统测试实现…

    2022年9月1日
  • mysql 时间戳换成日期格式_mysql 时间戳与日期格式的相互转换

    mysql 时间戳换成日期格式_mysql 时间戳与日期格式的相互转换1、UNIX时间戳转换为日期用函数:FROM_UNIXTIME()selectFROM_UNIXTIME(1156219870);输出:2006-08-2212:11:102、日期转换为UNIX时间戳用函数:UNIX_TIMESTAMP()SelectUNIX_TIMESTAMP(‘2006-11-0412:23:00’);输出:1162614180SelectUNIX_TIMEST…

    2022年6月21日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号