热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java编程特效_java函数式编程入门

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

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

什么是函数式编程

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

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

函数是”第一等公民”

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

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

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

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

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

没有”副作用”

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

函数式编程强调没有”副作用”,意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值.

不修改状态

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

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

引用透明

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

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

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

lambada表达式

基本表达形式如下:

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中,因此我们一般情况下不需再定义自己的接口,同时,各个接口的作用和名字都是相对应的,所以,了解函数式接口的命名模式就是很有必要的了。

以下是基本命名准则:

如果只处理对象而非基本类型,名称则为Function,Consumer,Predicate等。参数类型通过泛型添加。

如果接收的参数是基本类型,则由名称的第一部分表示,如LongConsumer,DoubleFunction,IntPredicate等,但基本Supplier类型例外。

如果返回值为基本类型,则用To表示,如ToLongFunction 和IntToLongFunction。

如果返回值类型与参数类型一致,则是一个运算符:单个参数使用UnaryOperator,两个参数使用BinaryOperator。

如果接收两个参数且返回值为布尔值,则是一个谓词(Predicate)。

如果接收的两个参数类型不同,则名称中有一个Bi。

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

特征

数式方法名

示例

无参数;

无返回值

Runnable

(java.lang)

run()

Runnable

无参数;

返回类型任意

Supplier

get()

getAs类型()

Supplier

BooleanSupplier

IntSupplier

LongSupplier

DoubleSupplier

无参数;

返回类型任意

Callable

(java.util.concurrent)

call()

Callable

1 参数;

无返回值

Consumer

accept()

Consumer

IntConsumer

LongConsumer

DoubleConsumer

2 参数 Consumer

BiConsumer

accept()

BiConsumer

2 参数 Consumer;

1 引用;

1 基本类型

Obj类型Consumer

accept()

ObjIntConsumer

ObjLongConsumer

ObjDoubleConsumer

1 参数;

返回类型不同

Function

apply()

To类型 和 类型To类型

applyAs类型()

Function

IntFunction

LongFunction

DoubleFunction

ToIntFunction

ToLongFunction

ToDoubleFunction

IntToLongFunction

IntToDoubleFunction

LongToIntFunction

LongToDoubleFunction

DoubleToIntFunction

DoubleToLongFunction

1 参数;

返回类型相同

UnaryOperator

apply()

UnaryOperator

IntUnaryOperator

LongUnaryOperator

DoubleUnaryOperator

2 参数类型相同;

返回类型相同

BinaryOperator

apply()

BinaryOperator

IntBinaryOperator

LongBinaryOperator

DoubleBinaryOperator

2 参数类型相同;

返回整型

Comparator

(java.util)

compare()

Comparator

2 参数;

返回布尔型

Predicate

test()

Predicate

BiPredicate

IntPredicate

LongPredicate

DoublePredicate

参数基本类型;

返回基本类型

类型To类型Function

applyAs类型()

IntToLongFunction

IntToDoubleFunction

LongToIntFunction

LongToDoubleFunction

DoubleToIntFunction

DoubleToLongFunction

2 参数类型不同

Bi操作

(不同方法名)

BiFunction

BiConsumer

BiPredicate

ToIntBiFunction

ToLongBiFunction

ToDoubleBiFunction

其中最常用的是:

92572b0a8312eb7eaf9416a21576b81c.png

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

class Foo {}

class Bar {

Foo f;

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

}

public class FunctionVariants {

static Function f1 = f -> new Bar(f);

public static void main(String[] args) {

Bar b = f1.apply(new Foo());

}

}

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

关于函数式编程的争议

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

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

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

参考文章

作者:笙歌会停



推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • NotSupportedException无法将类型“System.DateTime”强制转换为类型“System.Object”
    本文介绍了在使用LINQ to Entities时出现的NotSupportedException异常,该异常是由于无法将类型“System.DateTime”强制转换为类型“System.Object”所导致的。同时还介绍了相关的错误信息和解决方法。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
  • Spring框架《一》简介
    Spring框架《一》1.Spring概述1.1简介1.2Spring模板二、IOC容器和Bean1.IOC和DI简介2.三种通过类型获取bean3.给bean的属性赋值3.1依赖 ... [详细]
  • 本文详细介绍了在Linux虚拟化部署中进行VLAN配置的方法。首先要确认Linux系统内核是否已经支持VLAN功能,然后配置物理网卡、子网卡和虚拟VLAN网卡的关系。接着介绍了在Linux配置VLAN Trunk的步骤,包括将物理网卡添加到VLAN、检查添加的VLAN虚拟网卡信息以及重启网络服务等。最后,通过验证连通性来确认配置是否成功。 ... [详细]
author-avatar
heping的地盘2012
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有