Java中的函数式编程1

Functional Programming In OOP

引言

函数式编程是一种编程泛型,将所有的运算都视为函数,只要输入相同的数据,就能得到稳定的输出。然而由于它的抽象程度高,离计算机硬件远,因此并没有被工业界广泛使用。然而在许多面向对象的编程语言中,能看到函数式编程的影子,它们往往可以帮助我们减少代码重复、理解目标和代码管理等。所以,学习一定的函数编程思想是非常有必要的。本文主要以Java为示例,讲解在OOP语言中函数式编程的应用。

什么是函数?

作为一个理/工科生,一说到函数,也许就会想到数学定义上的函数:一个集合到另一个集合的双射。更加直观的说,函数就是:我们只要输入一些数据就能得到一些数据。这样的数据转换是由函数内部实现所决定的。当然把函数当成一种算法的实现也没有问题。总之一千个人眼中有一千个哈姆雷特,只要选择你自己能够理解的方法,理解它就可以了。

那么在计算机领域,函数有如下的一些特点:

  1. 每个函数的输入是确定的(数据的类型、个数)。
  2. 每个函数的输出是确定的(数据的类型),并且只能输出一个数据。
  3. 函数的内部应当避免使用程序状态可变对象

第一、二点很容易理解,函数体内部的实现依赖于输入和需求,而输出则依赖于函数的内部实现和输入,需求和函数内部实现是固定的,因此函数的输入和输出也应该是确定的。

函数可以没有输入或输出,但它会执行特定的功能。

对于第三点的理解,由于函数的内部实现的固定,因此不能把变化的(程序状态和可变对象)用在不变中。

什么是函数式编程?

在理解了函数是什么以后,我们就可以更进一步理解函数式编程了。

不同于OOP中万物皆对象的思想,函数式编程的思想更加的直接。将一系列的语句封装成多个不同的函数,从而解决一个复杂的问题;它聚焦于如何解决问题和表达式,而不是状态。

函数式方程还有以下特点:

  1. 递归:函数式编程采用递归处理while、if、for。
  2. 函数皆变量:所有的函数都可以当做变量使用。
  3. 不可变性:任何变量被创建以后都不能改变

函数式编程的优点:

  1. 易于debug
  2. Lazy evaluation:只在使用的时候运行函数。
  3. 支持并行编程:由于函数式编程使用不可变变量,因此可以轻松的实现并行编程,也不会有安全隐患。
  4. 易读:函数式编程的代码具有相当的易读性。
  5. 高效:函数式编程不依赖于外部资源或者变量,因此它们可以轻易的复用。

函数式编程的缺点:

  1. 术语复杂:函数编程的学习成本高。
  2. 递归:递归可能会造成资源浪费。

Java中函数式编程的应用

在Java中,函数式编程也有相当的应用场景。例如,对于一个排序算法:在不同的场景下可能要求升序或降序排列,为提高排序算法的可复用性,往往会需要一个东西,来控制排序的方式,也许可以是一个flag,若为1则升序,反之则降序。然而,通过这样的方式控制排序,过程中我们就必须重复书写一些代码,可以参考以下快速排序的实现。

    /**
     * 快速排序
     * 
     * @param arr   原数组
     * @param begin 起始元素
     * @param end   终止元素
     */
    public static void quickSort(int[] arr, int begin, int end, int flag) {
        if (begin >= end) {
            return;
        }

        int pivot = begin;
        int i = begin;
		if(flag == 1){
            for (int j = begin + 1; j <= end; ++j) {
            	if (arr[j] < arr[pivot]) {
                	swap(arr, ++i, j);
            		}
        		}
        }else {
            for (int j = begin + 1; j <= end; ++j) {
            	if (arr[j] > arr[pivot]) {
                	swap(arr, ++i, j);
            	}
        	}
        }
        
        swap(arr, i, pivot);

        quickSort(arr, pivot + 1, end, flag);
        quickSort(arr, begin, pivot - 1, flag);
    }

可以看到:for循环中除了比较大小不同,其它代码都相同。那么有没有什么办法,可以让我们避免重复书写相同代码呢?相信在看完函数式编程的简介以后,你就想到把一个函数当做参数传入方法中。那么接下来我们就要介绍如何使用这样的方法。

Java作为一个纯粹的OOP语言,万物皆为对象,所以我们所需要的函数参数也应该封装为一个类,这个类就代表着一个函数。显然这样的类不需要任何字段和其它方法,它的内部只有一个方法(封装的函数),因此使用接口(interface)来表示这个类最为恰当。

再回到快速排序这个例子,我们针对不同的排序方法,要使用同一段代码实现,所以我们需要函数既能表示“大于”,也能表示“小于”。一个函数两个作用,这显然涉及到了方法的覆写(@Override),现在思路就很清晰了,我们需要传入的函数参数应该是封装了函数的接口的具体实现类,在这个类中覆写了接口中的函数。

这就是在Java中使用函数作为参数的实现思路,那么具体实现将在下一节探讨。

  • 44
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沅筱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值