什么是函数式编程?
它是一种声明式的编程方式,而不是命令式的。这种编程的基本目标是使代码更简洁,更不复杂,更可预测,并且易于测试。
功能性编程涉及某些关键概念,如纯函数不可变,状态,无赋值编程等。
命令式编程与声明式编程
在命令式编程中,我们定义了做什么任务以及如何做。而在声明式编码中,我们只指定要做什么。让我们通过一个例子来理解这一点。
// Java program to find the sum
// using imperative style of coding
import java.util.Arrays;
import java.util.List;
public class ImperativeMainTest {
public static void main(String[] args)
{
List<Integer> numbers
= Arrays.asList(11, 22, 33, 44,
55, 66, 77, 88,
99, 100);
int result = 0;
for (Integer n : numbers) {
if (n % 2 == 0) {
result += n * 2;
}
}
System.out.println(result);
}
}
// Java program to find the sum
// using declarative style of coding
import java.util.Arrays;
import java.util.List;
public class DeclarativeMainTest {
public static void main(String[] args)
{
List<Integer> numbers
= Arrays.asList(11, 22, 33, 44,
55, 66, 77, 88,
99, 100);
System.out.println(
numbers.stream()
.filter(number -> number % 2 == 0)
.mapToInt(e -> e * 2)
.sum());
}
}
功能性编程包含以下关键概念。
- 函数是第一类对象
- 纯函数
- 高阶函数
作为第一类对象的函数
在函数式编程中,函数是语言中的第一类对象。这意味着语言支持将函数作为参数传递给其他函数,将其作为其他函数的值返回,并将其分配给变量或存储在数据结构中。在Java中,方法不是第一类对象。我们最接近的是Java Lambda表达式。
高阶函数
如果至少满足以下条件之一,一个函数就是一个高阶函数。
- 该函数接收一个或多个函数作为参数。
- 该函数返回另一个函数作为结果。
在Java中,我们能得到的最接近高阶函数的函数(方法)是以一个或多个lambda表达式为参数,并返回另一个lambda表达式。下面是一个Java中高阶函数的例子。
public class HigherOrderFunctionClass {
public <T> IFactory<T> createFactory(IProducer<T> producer, IConfigurator<T> configurator) {
return () -> {
T instance = producer.produce();
configurator.configure(instance);
return instance;
}
}
}
请注意,createFactory()方法返回一个lambda表达式作为结果。这就是高阶函数的第一个条件。
还请注意,createFactory()方法需要两个实例作为参数,这两个实例都是接口的实现(Iproducer和IConfigurator )。
想象一下,这些接口看起来像这样。
public interface IFactory<T> {
T create();
}
public interface IProducer<T> {
T produce();
}
public interface IConfigurator<T> {
void configure(T t);
}
正如你所看到的,所有这些接口都是功能接口。因此,它们可以通过Java lambda表达式来实现--因此,createFactory()方法是一个高阶函数。
如何在Java中实现函数式编程?
// Java 8 program to demonstrate
// a lambda expression
import java.util.Arrays;
import java.util.List;
public class FPMainTest {
public static void main(String[] args)
{
Runnable r
= ()
-> System.out.println(
"Running in Runnable thread");
r.run();
System.out.println(
"Running in main thread");
}
}
什么是纯函数?
一个函数是一个纯函数,如果。
- 函数的执行没有副作用。
- 函数的返回值只取决于传递给函数的输入参数。
下面是一个Java中纯函数(方法)的例子。
public class ObjectWithPureFunction{
public int sum(int a, int b) {
return a + b;
}
}
这里是一个非纯函数的例子。
public class ObjectWithNonPureFunction{
private int value = 0;
public int add(int nextValue) {
this.value += nextValue;
return this.value;
}
}
请注意,方法add() 使用一个成员变量来计算其返回值,它还修改了value 成员变量的状态,所以它有一个副作用。
纯函数式编程也有一套规则需要遵循。
- 没有状态
- 没有副作用
- 不可变的变量
- 倾向于递归而不是循环
什么是参照性透明?
如果一个函数在调用相同的参数值时总是返回相同的结果值,那么它就被称为参照透明。
为了实现参照透明,我们需要我们的函数是纯粹的和不可变的。
例如:"String.replace() "方法是参照透明的,因为如果 "shaurav.replace(`s`,`S`) "总是产生相同的结果,因为 "replace "方法返回新的对象,而不是将原来的对象升级。
纯函数是指代透明的表达式,纯函数应该根据传递的参数返回值,不应该影响或依赖全局状态。
例子:下面是纯函数的例子
public static int sum(int a, int b){
return a + b;
}
所以,这个函数也是参考透明的。
参考透明性使得每个子程序都是独立的,这在实施单元测试和重构的时候非常有帮助。另外,参照透明的程序更容易阅读和理解,这也是函数编程中需要参照透明的原因之一。