本篇内容介绍了“Java中的三种函数式编程怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

0. 函数式编程

函数式编程(Functional Programming)属于编程范式(Programming Paradigm)中的用语,此外还有命令式编程(Imperative Programing)等,有兴趣的同学可以自行了解,我们这里大概解释一下函数式编程,在函数式编程中,输入一旦确定了,输出都确定了,函数调用的结果只依赖于传入的输入变量和内部逻辑,不依赖于外部,这样的写出的函数没有副作用。举个例子:

publicclassPerson{privateinta=1;publicintadd(intb){returna+b;}publicintpow(intc){returnc*c;}publicstaticvoidmain(String[]args){Personp=newPerson();p.add(1);p.pow(2);}}

上面代码中add(int b)这个方法就不符合函数式编程,这个函数调用后的结果不确定,它的结果不仅取决于b还取决于字段a。而pow(int c)这函数就是符合函数式编程的典范,只要调用它,输入的值c确定了返回值就肯定确定了。
在函数式编程中,函数也是一等公民,可以被当做参数传递,可以被赋值,被引用,可以把它当做一种数据类型来对待,如果你会使用javascript之类的语言就可以有更深的体会。如果要深入了解这种编程范式可以自行网上搜素资料了解。

1. lambda表达式

lambda表达式是jdk8中的新特性,上面讲函数式编程就是引入这个,oracle在jdk8中引入了lambda,从此Java中开始对函数式编程的部分支持。
Java中lambda表达式的语法结构:(params) -> expression。由三部分构成,第一部分是括号以及括号内部的形式参数,第二部分是"->"箭头符号,第三部分是expression方法体,方法体可以是代码块也可以是执行表达式。

//1.lambda表达式的完整形态:有输入参数,有返回值,有代码块。(inta,intb)->{intc=a+b;returnc;}//2.lambda表达式在某些情况也可以省略一部分//2.1当代码块不需要返回值的时候可以省略return语句(inta,intb)->{intc=a+b;}//2.2当代码块只有一句的时候可以省略大括号//并且这种情况默认返回这一句代码的执行结果(inta,intb)->a+b;//同1具有同样的作用//2.3形参的类型可以根据函数式接口的里面的方法声明自行推断//可以省略形参类型(a,b)->a+b;//同1,2.2具有同样的效果//2.4当只有一个参数的时候可以省略,形参的小括号a->a*a;

接下来展示一个从定义接口到使用lambda表达式的代码

/***description:**@authorwaxxd*@version1.0*@date2019-10-15**/publicclassTest1{privateinta=1;privateintb=2;/***这个方法需要一个IAdd类型的参数*@paramadd*@return**/publicintadd1(IAddadd){returnadd.add(a,b);}publicstaticvoidmain(String[]args){Test1test1=newTest1();//使用lambda表达式intc=test1.add1((a,b)->a+b);System.out.println(c);//使用匿名类intd=test1.add1(newIAdd(){@Overridepublicintadd(inta,intb){returna+b;}});System.out.println(d);}}/***description:*函数式接口,里面抽象方法只能有一个*@authorwaxxd*@version1.0*@date2019-10-15**/@FunctionalInterfacepublicinterfaceIAdd{intadd(inta,intb);}

可以看见使用lambda表达式的方式相对于匿名类代码会精简优雅很多,下面给出一个经常使用的例子,创建线程:

publicclassTest(){publicstaticvoidmain(String[]args){Threadt1=newThread(newRunable(){System.out.println("使用匿名类的方式创建线程");});Threadt2=newThread(()->System.out.println("使用lambda方式创建线程"));t1.start();t2.start();}}2. 双冒号::符号

这个符号第一次看见是在c++里面,在c++里面是一个类似标识作用域解析符号或者范围的符号,描述可能不准确,对c++有兴趣的同学可以自行查找。如果了解c++,这个操作符号就勉强类似类似在c++中函数指针,::在Java里面也可以叫做方法引用,就上面说的函数也是一等公民,这里就类似把方法作为参数传入。前面的例子我们使用lambda表达式都类似使用匿名类实现接口的方法,然而还有一种情况我们并不想要自己去实现接口的方法,只是想传进去一个已经有过实现了的方法,就可以使用::,它的语法规则如下:
类名::静态方法名 或者 类的实例::实例方法。

List<File>list=newArrayList<>;list.forEach(File::getName);//使用双冒号传递一个函数进来,list.forEach(file->file.getName());//使用正常的lambda表达式3. Optional类

Optional也是jdk8中的一个新的类的,它给予我们更加优雅的方式来处理Java语言中的NPE异常。可以从一定程度上代替if判断, 介绍相关接口:

empty 创建一个空的Optional对象

of 和ofNullable

of创建一个Optional对象, 如果传入的参数为空则跑出NPE异常.
ofNullable和上面一样, 但是当传入参数为空的时候会调用empty方法创建一个空Optional对象.

Optional<String>of=Optional.of("waxxd");//传入空参数会抛出NullPointerException异常Optional<String>ofNull=Optional.of(null);//以下两句都正常执行Optional<String>ofNullable=Optional.ofNullable("waxxd");//参数为空的时候相当调用Optional.empty()Optional<String>ofNullableNull=Optional.ofNullable(null);

get/orElse/orElseGet/orElseThrow

//get获取Option包裹的值如果值为null则抛出NoSuchElementException异常Stringaa=Optional.of("aa").get();//orElse获取值如果值为空则返回orElse设置的默认值Stringaa1=Optional.of("aa").orElse("bb");//orElseGet获取值如果值为空则内部可以是一个实现Supplier接口的匿名内部类调用提供返回结果Stringaa2=Optional.of("aa").orElseGet(()->"aaa".toUpperCase());//orElseThrow获取值如果不存在则抛出后面的异常Optional.empty().orElseThrow(IllegalArgumentException::new);//实际的应用,也就是上文所说的如何优化if//比如你有个接口,用户传入参数Integertype,用户也可以选择不传,不传我们为它设置默认值1publicvoidf(Integertype){if(type=null){type=1;}Optional.ofNullable(type).orElse(1);}

“Java中的三种函数式编程怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!