Java的函数式编程详解

 更新时间:2023年10月24日 08:20:46   作者:在下uptown  
用了这么久的Java8,我寻思这种话也好意思说出来吗,难道自己是PythonBoy出身就是看不懂Java的理由吗,身为一个合格的后端Boy不会还有人看不明白Java的函数式编程吧,接下来小编和大家浅聊一下Java的函数式编程,需要的朋友可以参考下

前言

虽然Jdk版本已经出到了20+,甚至IDEA创建maven默认项目Jdk版本都11了,但是你发任你发,我用Java8,最近别的组的同事要对接个需求,把代码仓库开给他之后反馈看不太明白代码。

用了这么久的Java8,我寻思这种话也好意思说出来吗,难道自己是PythonBoy出身就是看不懂Java的理由吗,身为一个合格的后端Boy不会还有人看不明白Java的函数式编程吧。

函数式编程

那什么是函数编程呢,说白了就是可以把函数作为参数传递给其他函数,亦或者将一个函数作为返回值从另一个函数中返回。

于是Jdk根据不同的场景提供了一些核心特性和函数式接口:

Consumer<T>:接受一个输入参数 T,并在方法内部执行操作,没有返回值。

Supplier<T>:不接受任何输入参数,提供一个结果 T。

Function<T, R>:接受一个输入参数 T,执行操作并返回一个结果 R。

Predicate<T>:接受一个输入参数 T,返回一个布尔值表示是否满足条件。

UnaryOperator<T>:接受一个输入参数 T,执行操作并返回一个与输入参数类型相同的结果。

BinaryOperator<T>:接受两个相同类型的输入参数 T,执行操作并返回一个相同类型的结果。

相信大家经常在业务代码中有过这样的场景,DAO层返回了一个Optional类,如果我们只想获得其中的某一个属性应该怎么写。

我们借助一个小菜鸡老弟的代码说,这段代码写的只能说一言难尽,按照他的想法,他只想拿到age字段,其实我们只需要借助map即可满足需求。

aa.map(Studnet::getAge)
.orElseThrow(
   () -> throw new Exception("user not found")
);

这里的orElseThrow其实就是传进去的一个方法,我们可以在方法里做些别的事,比如打印下信息之类的

aa.map(Student::getAge).orElseThrow(() -> {
    System.out.println("error! error!");
    return new Exception("user not found");
});

这就是一个很简单的函数式编程例子,把函数作为参数,在另一个函数中调用。这里举一个真实的业务案例,根据高内聚低耦合的抽象思想,我们保存数据的时候做一层前置数据校验,不同的类有不同的检查字段和方法,比如Student类要检查年龄是否大于18岁。

public class Java8Test {

    public static void main(String[] args) {
        Student student1 = Student.builder().age(10).name("uptown").build();
        savePeople(student1, (Student s1) -> {
            if (s1.getAge() < 18) {
                throw new RuntimeException("18岁禁!");
            }
        });
    }

    public static <T extends People> void savePeople(T t, Consumer<T> function) {
        function.accept(t);
        // 业务TODO
    }
}

@Data
@Builder
class People {

}

@Data
@Builder
class Student extends People {
    Integer age;
    String name;
}

这样写是不是比叠加if语句优化很多。

闭包

熟练使用函数式编程的jym对这个概念肯定不陌生,闭包就是能够读取其他函数内部变量的函数,借助网上js闭包的例子。

function makeFunc() {
	var name = "Mozilla";
	function displayName() {
		console.log(name);
	}
	return displayName;
}

var myFunc = makeFunc();
myFunc(); // "Mozilla"

可以通俗的想象成,你在房间里写了一段代码包含一个函数和一些变量。当你离开房间后,函数和变量仍然存在,它们就形成了一个闭包。当你再次进入房间时,你可以使用闭包中的函数来访问和修改之前已经修改过的变量,变量仍然记录着之前的状态。

那么Java中是否有闭包特性呢,答案是严格意义上说没有。

因为仔细想一下就发现在JVM里这套逻辑显然不符合,在栈中的变量函数结束后就会被清掉,怎么会记住之前的结果。但我们可以通过匿名内部类或lambad表达式实现,lambad本质上也是匿名内部类。

public static void main(String[] args) {
    final int i = 0;
    Supplier<Integer> sup = new Supplier<>(){
        Integer get(){
            return i;
        }
    };
}

为了保证正确性和一致性,JDK在语法上规定了lambad内部访问的局部变量必须是final修饰的。因为lambda表达式本质上创建了一个闭包,捕获了外部的局部变量,并在Lambda表达式的函数体中使用这些变量。

这只是其中一点,变量修饰为final还有一些数据一致方面的问题,这里就不再赘述了。

以上就是Java的函数式编程详解的详细内容,更多关于Java函数式编程的资料请关注脚本之家其它相关文章!

相关文章

  • java实现构造无限层级树形菜单

    java实现构造无限层级树形菜单

    这篇文章主要介绍了java实现构造无限层级树形菜单,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • 如何实现java Iterator迭代器功能

    如何实现java Iterator迭代器功能

    这篇文章主要介绍了如何实现java Iterator迭代器功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • 一个牛人给Java初学者的建议(必看篇)

    一个牛人给Java初学者的建议(必看篇)

    下面小编就为大家带来一篇一个牛人给Java初学者的建议(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 彻底搞懂Java多线程(四)

    彻底搞懂Java多线程(四)

    这篇文章主要给大家介绍了关于Java面试题之多线程和高并发的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2021-07-07
  • Java带返回值的方法的定义和调用详解

    Java带返回值的方法的定义和调用详解

    在java中,方法就是用来完成解决某件事情或实现某个功能的办法。方法实现的过程中,会包含很多条语句用于完成某些有意义的功能——通常是处理文本,控制输入或计算数值,这篇文章我们来探究一下带返回值的方法的定义和调用
    2022-04-04
  • Java8中的Stream 流实践操作

    Java8中的Stream 流实践操作

    这篇文章主要介绍了Java8中的Stream 流实践操作,Stream 是 java8 中处理集合的抽象概念,可以执行非常复杂的查询、过滤和映射数据等操作,下文更多相关资料介绍,需要的朋友可以参考一下
    2022-05-05
  • 教你快速搭建sona服务及idea使用sona的方法

    教你快速搭建sona服务及idea使用sona的方法

    Sonar 是一个用于代码质量管理的开放平台。通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具,本文给大家分享搭建sona服务及idea使用sona的方法,感兴趣的朋友一起看看吧
    2021-06-06
  • SpringSecurity+Redis+Jwt实现用户认证授权

    SpringSecurity+Redis+Jwt实现用户认证授权

    SpringSecurity是一个强大且灵活的身份验证和访问控制框架,本文主要介绍了SpringSecurity+Redis+Jwt实现用户认证授权,具有一定的参考价值,感兴趣的可以了解一下
    2024-07-07
  • 详解@Autowired是如何注入变量的

    详解@Autowired是如何注入变量的

    在 Spring 容器中,当我们想给某一个属性注入值的时候,有多种不同的方式,例如使用 @Autowired、@Inject等注解,下面小编就来和小伙伴们聊一聊,@Autowired 到底是如何把数据注入进来的
    2023-07-07
  • 如何将maven项目划分为多个模块

    如何将maven项目划分为多个模块

    这篇文章主要介绍了如何将maven项目划分为多个模块,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09

最新评论