函数式编程解析:定义、功能与Java实践

目录

  • 一、函数式编程
    • 1.1 什么是函数式编程
    • 1.2 函数式编程特征
      • 1.2.1 纯函数
      • 1.2.2 函数是一等公民
    • 1.3 函数式编程在java中的实践
  • 参考资料

一、函数式编程

1.1 什么是函数式编程

函数式编程(Functional Programming)是一种编程范式,它将计算视为数学函数的求值,强调使用纯函数和不可变数据。

除了函数式编程之外, 还有 命令式编程,声明式编程 等编程范式。

在函数式编程中,函数是一等公民,它可以作为参数传递给其他函数,也可以作为返回值返回。函数式编程避免了副作用(Side Effects)和共享状态,这样可以提高代码的可维护性、可测试性和并发性。

1.2 函数式编程特征

以下是函数式编程的一些主要特征:

  1. 纯函数(Pure Functions): 函数的输出只依赖于输入,不依赖于任何外部状态或可变数据。相同的输入始终产生相同的输出,而且没有副作用。
  2. 不可变数据(Immutable Data): 数据一旦被创建就不能被更改。如果需要修改数据,通常会创建一个新的数据副本。
  3. 函数是一等公民(First-Class Functions): 函数跟其它的数据类型一样处于平等地位,可以被当作参数传递给其他函数,也可以被作为返回值返回。
  4. 高阶函数(Higher-Order Functions): 函数可以接受一个或多个函数作为参数,并且可以返回一个函数。
  5. 递归(Recursion): 在函数式编程中,递归是一种常见的控制结构,因为循环通常依赖于可变状态,而函数式编程强调不可变性。
  6. Lambda 表达式: Lambda 表达式是一种匿名函数,它允许在代码中直接定义简短的函数。
  7. 惰性求值(Lazy Evaluation): 只在需要时计算表达式的值,而不是在每个可能的地方都计算。
  8. 模块化和组合性(Modularity and Compositionality): 将问题分解为小的、可复用的函数,通过组合这些函数来构建更复杂的功能。

函数式编程最重要的特征是 纯函数函数是一等公民

函数式编程不是一个特定语言的概念,而是一种编程风格或哲学。虽然一些编程语言(如Haskell、Scala、Clojure)更天然地支持函数式编程,但在越来越多的编程语言中,如Java、JavaScript、Python,也引入了函数式编程的特性。函数式编程的思想对于处理并发、提高代码可维护性和表达力都有很大的帮助。

1.2.1 纯函数

纯函数是指相同的输入总会得到相同的输出,并且不会产生副作用的函数。纯函数的两个特点:

  • 相同的输入必有同输出
  • 无副作用。无副作用 指的是函数内部的操作不会对外部产生影响(如修改全局变量的值等)。

举个例子,

public class Person{private int a = 1;public int add(int b){return a + b;}public int pow(int c){return c * c;}public static void main(String[] args){Person p = new Person();p.add(1);p.pow(2);}
}

上面代码中add(int b)这个方法就不符合函数式编程,这个函数调用后的结果不确定,它的结果不仅取决于b还取决于字段a。而pow(int c)这函数就是符合函数式编程的典范,只要调用它,输入的值c确定了返回值就肯定确定了。

1.2.2 函数是一等公民

在编程语言中,将函数视为一等公民(First-Class Citizen)意味着函数具有以下特性:

  1. 可以赋值给变量: 可以将函数赋值给变量,使得函数可以像其他数据类型一样在程序中被存储和传递。
  2. 可以作为参数传递: 可以将函数作为参数传递给其他函数,这使得函数可以参与更高阶的操作,如函数的组合和转换。
  3. 可以作为返回值: 函数可以作为其他函数的返回值,使得函数可以生成和返回其他函数。
  4. 可以存储在数据结构中: 函数可以存储在数组、列表、集合等数据结构中,允许对函数进行组织和管理。

在支持函数作为一等公民的编程语言中,函数与其他数据类型(如整数、字符串等)具有相同的地位,可以像操作其他数据一样灵活地使用。这种特性是函数式编程风格的核心之一。

举个简单的例子,假设有一个接受两个整数和一个函数作为参数的函数 operate

@FunctionalInterface
public interface IntBinaryOperator {int applyAsInt(int left, int right);// 其他默认方法和静态方法...
}public class FunctionAsFirstClassCitizenExample {// 函数作为参数public static int operate(int a, int b, IntBinaryOperator operator) {return operator.applyAsInt(a, b);}// 函数作为返回值public static IntBinaryOperator getOperator(String operation) {switch (operation) {case "+":return (x, y) -> x + y;case "-":return (x, y) -> x - y;case "*":return (x, y) -> x * y;default:throw new IllegalArgumentException("Unsupported operation: " + operation);}}public static void main(String[] args) {// 函数赋值给变量IntBinaryOperator addition = (x, y) -> x + y;// 函数作为参数传递int result = operate(5, 3, addition);System.out.println("Result of addition: " + result);// 函数作为返回值IntBinaryOperator selectedOperator = getOperator("*");// 调用返回的函数int result2 = operate(4, 2, selectedOperator);System.out.println("Result of multiplication: " + result2);}}

在这个例子中,IntBinaryOperator 是 Java 中的一个函数式接口,用于表示接受两个整数参数并返回一个整数结果的操作。它定义了一个抽象方法 applyAsInt(int left, int right),用于执行具体的整数操作。函数 operate 接受两个整数和一个函数作为参数,函数 getOperator 返回一个函数。。这展示了函数作为一等公民的特性,可以方便地传递和组合。

1.3 函数式编程在java中的实践

Java 8 引入了对函数式编程的支持,主要通过以下几个特性来实现:

  1. Lambda 表达式: Lambda 表达式是 Java 8 中引入的一个重要特性,它使得能够以更为简洁的方式表示匿名函数。Lambda 表达式可以用来实现函数式接口(只包含一个抽象方法的接口)。

    javaCopy code// 旧的方式使用匿名内部类
    Runnable runnable1 = new Runnable() {@Overridepublic void run() {System.out.println("Hello, World!");}
    };// 使用 Lambda 表达式
    Runnable runnable2 = () -> System.out.println("Hello, World!");
    
  2. 函数式接口: 函数式接口是一个只包含一个抽象方法的接口。Java 8 引入了 @FunctionalInterface 注解来标识函数式接口,以便编译器检查。常见的函数式接口包括 RunnableCallableComparator 等。

    javaCopy code@FunctionalInterface
    interface MyFunction {void apply();
    }
    
  3. Stream API: Stream API 提供了一种对集合进行声明式操作的方式,支持函数式编程风格的数据处理。它允许对集合进行过滤、映射、归约等操作,而不需要显式使用循环。

    javaCopy codeList<String> words = Arrays.asList("apple", "banana", "orange");// 使用 Stream 进行操作
    long count = words.stream().filter(word -> word.length() > 5).count();
    
  4. 默认方法和静态方法: 接口中引入的默认方法和静态方法使得在接口中引入新方法变得更为灵活。这对于在函数式编程中向接口添加新功能非常有用,而不会破坏现有实现。

    javaCopy codeinterface MyInterface {default void defaultMethod() {System.out.println("Default method");}static void staticMethod() {System.out.println("Static method");}void abstractMethod();
    }
    
  5. Optional 类: Optional 类是 Java 8 引入的一个用于处理可能为 null 的值的容器类。它通过一系列的函数式方法来支持更安全、更函数式的处理空值的方式。

    javaCopy codeOptional<String> name = Optional.ofNullable(getName());
    String result = name.orElse("Unknown");
    

这些特性使得 Java 在某种程度上支持函数式编程范式,尽管 Java 仍然是一门面向对象编程的语言。除了以上特性,一些第三方库,如Guava和Vavr,提供了更多函数式编程支持的工具和数据类型。在 Java 9、Java 10 和 Java 11 中,也进一步增强了函数式编程的支持,例如引入了模块化系统和新的集合操作方法。

参考资料

什么是「函数式编程」? - 知乎 (zhihu.com)

详解Java中的三种函数式编程,以及具体的实现方法 | w3cschool笔记

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/213592.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ES6中的迭代器和set、map集合

什么是迭代器&#xff1f; 一种机制&#xff0c;也是一种接口&#xff0c;为数据结构提供统一访问接口&#xff0c;依次处理数据据结构成员 只要实现了迭代器接口&#xff0c;就可以使用for...of循环遍历。 /*** 迭代器是一种机制 是一种接口 只要数据解构实现了接口 就可…

力扣labuladong一刷day36天

力扣labuladong一刷day36天 一、96. 不同的二叉搜索树 题目链接&#xff1a;https://leetcode.cn/problems/unique-binary-search-trees/ 思路&#xff1a;这是一道典型的动态规划题&#xff0c;从n3来看 子树有几种形态 (0, 2)、(1, 1)、(2, 0)有规律可循&#xff0c;即为左…

飞天使-linux操作的一些技巧与知识点4

文章目录 ansible配置文件的优先级尝试开始进行操作ansible常用模块ansible 的playbook示例安装phpplaybook中变量的引用 ansible yum install -y ansible 测试是否可用 ansible localhost -m ping /etc/ansible/ansible.cfg &#xff1a;主配置文件&#xff0c;配置 ansible…

大公司求我用Kotlin写个通用爬虫模板

bug虐我千百遍&#xff0c;我待他如初恋。每次深夜挑灯都是我与bug较量的时间。今天我要说的就是写一个爬虫模版&#xff0c;自动抓取百度图片的教程&#xff0c;这次使用Kotlin编写的爬虫程序在Scrapy框架下完成的&#xff0c;如有不足欢迎指正。 首先&#xff0c;使用Kotlin编…

Mybatis-Plus源码解析之@MapperScan(一)

group : com.baomidou version:3.5.2.2-SNAPSHOT baomidou官网可以从快速开始了解到&#xff0c;除了配置数据源&#xff0c;最重要的就是MapperScan 注解&#xff0c;在 Spring Boot 启动类中添加 MapperScan 注解&#xff0c;扫描 Mapper 文件夹。 MapperScan 按照惯例&…

angular form 组件、双向绑定;反应式表单

1.使用双向绑定&#xff0c;以及angular的表单提交功能 app.moudle中引入 双向绑定 [(ngModel)]"text" ​​​​​​​ 效果 提交表单 2.反应式表单 在app.module.ts中引入在组件中引入&#xff0c;并放在一个变量里 在初始化时实列化这个module 定义规则 在html…

Linux:环境变量

目录 1.基本变量 2.通过代码获取环境变量 2.1 main传参 2.2 全局变量environ 2.3 系统调用getenv() 3.在脚本文件中添加环境变量 4.环境变量通常是具有全局属性 1.基本变量 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数…

商用中央空调市场分析:预计2028年将达到628亿元

商用空调一直以来都没有一个相对比较明确的概念&#xff0c;一直以来被认为是制冷空调市场的一个细分子行业。现在比较一致的观点是&#xff0c;可以纳入商用空调范畴的产品可以包括户式中央空调产品、部分传统中央空调产品以及部分家用空调。商用空调已普遍采用直流变频领先技…

网络计算机模拟实现

今天给大家说说前几天完成的一个模拟的网络计算机吧&#xff0c;虽然计算机的模拟实现的原理很简单&#xff0c;但是如果要想写乘网络的&#xff0c;个人认为是不简单的。基本上算是包涵了套接字编程的三分之一的知识点&#xff0c;此处的套接字编程指的是在理解TCP/IP五层协议…

泡沫玻璃市场分析:预计2028年将达到14亿美元

泡沫玻璃最早是由美国匹兹堡康宁公司发明的&#xff0c;是由碎玻璃、发泡剂、改性添加剂和发泡促进剂等&#xff0c;经过细粉碎和均匀混合后&#xff0c;再经过高温熔化&#xff0c;发泡、退火而制成的无机非金属玻璃材料。它是由大量直径为1~2毫米的均匀气泡结构组成。其中吸声…

Linux 常用命令----mktemp 命令

文章目录 基本用法实例演示高级用法注意事项 mktemp 命令用于创建一个临时文件或目录&#xff0c;这在需要处理临时数据或进行安全性测试时非常有用。使用 mktemp 可以保证文件名的唯一性&#xff0c;避免因文件名冲突而导致的问题。 基本用法 创建临时文件: 命令 mktemp 默认…

Go语言基础知识学习(一)

Go基本数据类型 bool bool型值可以为true或者false,例子&#xff1a; var b bool true数值型 类型表示范围int8有符号8位整型-128 ~ 127int16有符号16位整型-32768 ~ 32767int32有符号32位整型-2147783648 ~ 2147483647int64有符号64位整型uint8无符号8位整型0 ~ 255uint16…

优思学院|如何建立公司运营指标体系?如何推行六西格玛改进运营指标?

关键绩效指标 (KPI) 是测量您团队或组织朝重要商业目标进展表现如何的量化指标&#xff0c;组织会在多个层面使用 KPI&#xff0c;这视乎您想要追踪何指标而定&#xff0c;您可以设定全组织的、特定团队的、或甚至是个人 KPI。 良好的KPI能让公司管理者掌握组织的营运是否进度…

使用React 18、Echarts和MUI实现温度计

关键词 React 18 Echarts和MUI 前言 在本文中&#xff0c;我们将结合使用React 18、Echarts和MUI&#xff08;Material-UI&#xff09;库&#xff0c;展示如何实现一个交互性的温度计。我们将使用Echarts绘制温度计的外观&#xff0c;并使用MUI创建一个漂亮的用户界面。 本文…

点评项目——分布式锁

2023.12.10 集群模式下的并发安全问题及解决 随着现在分布式系统越来越普及&#xff0c;一个应用往往会部署在多台机器上&#xff08;多节点&#xff09;&#xff0c;通过加锁可以解决在单机情况下的一人一单安全问题&#xff0c;但是在集群模式下就不行了。见下图&#xff1a…

在 Android WebView 中实现和 JavaScript 的互操作

前言 在 APP 中内嵌一个 H5 来实现特定的业务功能已经是非常成熟且常用的方案了。 虽然 H5 已经能够实现大多数的需求&#xff0c;但是对于某些需求还是得依靠原生代码来实现然后与 JavaScript 进行交互&#xff0c;例如我目前所负责的项目就是一个 “智能硬件” 设备&#x…

【PyTorch】卷积神经网络

文章目录 1. 理论介绍1.1. 从全连接层到卷积层1.1.1. 背景1.1.2. 从全连接层推导出卷积层 1.2. 卷积层1.2.1. 图像卷积1.2.2. 填充和步幅1.2.3. 多通道 1.3. 池化层&#xff08;又称汇聚层&#xff09;1.3.1. 背景1.3.2. 池化运算1.3.3. 填充和步幅1.3.4. 多通道 1.4. 卷积神经…

实现React18加TS,解决通用后台管理系统,实战方案落地有效实践经验

随着前端技术的不断发展和更新&#xff0c;使用React 18结合TypeScript&#xff08;TS&#xff09;来构建通用后台管理系统已成为一种常见的选择。本文将介绍如何在项目中应用React 18和TS&#xff0c;并分享一些实战方案的有效实践经验。 一、搭建React 18 TS项目 首先&…

12.2每日一题(1无穷型幂指函数:二倍角公式+三部曲+等价无穷小代换(只有整体的因子不为0才能先算出来))

注意&#xff1a;求极限不能想先算哪里就先算哪里&#xff0c;只有整体的因子不为0才能先算出来&#xff0c;部分不为0不可以先算

外贸老业务也棘手的一个问题

这几天有2个老业务都被一个类同的问题缠住了。 客户定购了三台车&#xff0c;由于是非常规要求所以我建议收取全款或者最少收50%的定金。但是业务员为了当月业绩或者为了拿到就收了客户20% 或者30% &#xff0c;定金收到了&#xff0c;我也不好再逼着业务员去加收定金。 订单就…