我在 WebFlux 教程中已经阐明了一种观点,函数式编程(Functional programming)将成为未来编程的一种趋势。我们也可以从 Java 8 等新版本中看到这种趋势。所以关于函数式编程的原理,优缺点?什么是函数式编程?等问题,我做一个总结,希望能够方便到大家的学习和理解!
什么是函数式编程?
函数式编程的第一个特点就是可以把函数作为参数传递给另一个函数,也就是所谓的高阶函数。例如,对数组进行排序,可以传入一个排序函数作为参数:
String[] array = { "xttblog", "yyucao", "www.xttblog.com" }; Arrays.sort(array, String::compareToIgnoreCase);
函数式编程的第二个特点就是可以返回一个函数,这样就可以实现闭包或者惰性计算。
函数式编程的好处
那么根据简化了的函数式编程的特点,函数式编程有什么好处呢?
从代码的可维护性上讲,函数式编程最大的好处是引用透明,即函数运行的结果只依赖于输入的参数,而不依赖于外部状态,因此,我们常常说函数式编程没有副作用。
没有副作用有个巨大的好处,就是函数内部无状态,即输入确定,输出就是确定的,容易测试和维护。
下面我们通过一个例子来看它的好处!
比如一个财务软件,需要一个函数专门计算个人所得税,输入是一个 IncomeRecord,输出是个税金额:
double calculateIncomeTax(IncomeRecord record) { // 省略具体实现 }
然后假设 IncomeRecord 长这样:
class IncomeRecord { String carId; // 身份证号 String name; // 姓名 double salary; // 工资 String address;// 地区 }
然后,我们不考虑其它的社保、公积金等乱七八糟的东西内容。我们只简化为,扣减一个免征额后多月的按 20% 的税收计算。
double threshold = 3500; // 免征额 double calculateIncomeTax(IncomeRecord record) { if(record.salary <= threshold){ return 0; }else{ return (record.salary - threshold) * 0.2; } }
上面这个程序在 2018 年 10 月 1 号前是没问题的,问题是 2018 年 10 月 1 号后起征点调整到了 5000,那 2018 年 9 月和 2018 年 10 月,计算结果应该不一样。上面的税收方式就需要调整?怎么调整呢?
double threshold = today() < date(2018, 10, 1) ? 3500 : 5000; // 免征额 double calculateIncomeTax(IncomeRecord record) { if(record.salary <= threshold){ return 0; }else{ return (record.salary - threshold) * 0.2; } }
这样改代码,看起来没错,但是在实际运行中,可能会出问题。
比如,我们 10 月份,实际上发的是 9 月份的工资吧。这个系统,在 9 月 30 号跑,和 10 月 1 号跑,结果不一样。比如,我们在 10 月 2 号这天发工资。但是这次发工资我们是按照上月的考勤来统计个税的,然后会计要在 10 月 1 号做 9 月份的工资条,和 9 月 30 号做工资条,结果并不一致。难道要求会计必须把电脑的时间先调到 9 月份?
所以,这个问题,我们用函数式编程思维就很好解决了。calculateIncomeTax() 不再是一个纯函数,它与当前时间相关了。现在我们把它变成一个纯函数。
class IncomeRecord { String id; // 身份证号 String name; // 姓名 double salary; // 工资 String address;// 地区 int year; // 年 int month; // 月 }
calculateIncomeTax 函数也在调整一下:
double calculateIncomeTax(IncomeRecord record) { double threshold = date(record.year, record.month) < date(2018, 10) ? 3500 : 5000; if(record.salary <= threshold){ return 0; }else{ return (record.salary - threshold) * 0.2; } }
虽然这个问题,不用函数式编程也能解决。但是拥有函数式编程思维比解决问题本身更重要。
总的来说,函数式编程强调将计算过程分解成可复用的函数,典型例子就是 map 方法和 reduce
方法组合而成 MapReduce 算法。更多函数式编程知识,请参考我的 WebFlux 教程!
: » 函数式编程的原理和优点
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/tech/java/252012.html