定义
程序可以用一系列的数学函数表达;
JAVA实现
- Stream 类 + Lambda + 函数式接口
Stream 类用来支持通过“.”级联多个函数操作的代码编写方式;引入 Lambda 表达式的作用是简化代码编写;函数接口的作用是让我们可以把函数包裹成函数接口,来实现把函数当做参数一样来使用(Java 不像 C 一样支持函数指针,可以把函数直接当参数来使用)。
“.”表示调用某个对象的方法。为了支持上面这种级联调用方式,我们让每个函数都返回一个通用的类型:Stream 类对象。在 Stream 类上的操作有两种:中间操作和终止操作。中间操作返回的仍然是 Stream 类对象,而终止操作返回的是确定的值结果。我们再来看之前的例子。我对代码做了注释解释,如下所示。其中,map、filter 是中间操作,返回 Stream 类对象,可以继续级联其他操作;max 是终止操作,返回的不是 Stream 类对象,无法再继续往下级联处理了。
public class FPDemo {
public static void main(String[] args) {
Optional<Integer> result = Stream.of("f", "ba", "hello") // of返回Stream<String>对象
.map(s -> s.length()) // map返回Stream<Integer>对象
.filter(l -> l <= 3) // filter返回Stream<Integer>对象
.max((o1, o2) -> o1-o2); // max终止操作:返回Optional<Integer>
System.out.println(result.get()); // 输出2
}
}```
## Lambda表达式
Lambda是一个匿名函数(相似于匿名内部类),作用是返回一个实现了接口的对象. 简化创建实现接口的对象的过程.
Lambda只能用于函数式接口(只有一个抽象方法的接口, 用注解@FunctionalInterface标识)
Lambda的基本语法
小括号() : 形式参数列表
大括号{} : 描述方法体
-> : Lambda运算符(读作goes to),用于分割上面两个元素
//一个没有参数, 没有方法体的Lambda表达式
()->{}
写法:省略实现接口的类名、省区接口名、省区方法名字,保留核心的参数,函数内容;
优势
Lambda表达式比起传统的匿名内部类, 其优势就是有很多可省略的地方, 相较而言更简洁明了.
Lambda表达式可省略的原则: 凡是可根据上下文推断得到的, 就可以省去.
![在这里插入图片描述](https://img-blog.csdnimg.cn/e392da79fb5f45b096df1ee4dfee6ab8.png)
方法(函数)引用
方法引用返回的类型不再是接口的实例对象.
为什么需要它
当我们使用多个 接口实现对象 , 它们执行的指令相同. 但如果后面要改, 那么修改成本很高. 那么把这些指令单独出来成为一个方法, 就可以解决这个问题.
所以方法引用只能适用于方法已存在的情况
格式
“方法的隶属者::方法名”,如:String::toUpperCase
方法的隶属者: 静态方法的则是类; 非静态方法则是对象. 隶属者不是接口, 而是定义方法的类或对象.
被引用的方法参数和类型和一定要和接口的方法一致. 而且也要返回值类型也要一致.
方法名的后面没有括号"()"
方法引用可以有多个参数入口,尽管在表达式中省略括号看不到,实际上在接口中会有规定.
各种引用示例
0. 各种函数式接口(便于后面演示)
//1.无返回值的多参接口
@FunctionalInterface
public interface LambdaNoneReturnMultipleParameter {
void test(int a, int b);
}
//2.无返回值的无参接口
@FunctionalInterface
public interface LambdaNoneReturnNoneParameter {
void test();
}
//3.无返回值的一参接口
@FunctionalInterface
public interface LambdaNoneReturnSingleParameter {
void test(int n );
}
//4.有返回值的多参接口
@FunctionalInterface
public interface LambdaSingleReturnMultipleParameter {
int test(int a, int b);
}
//5.有返回值的无参接口
@FunctionalInterface
public interface LambdaSingleReturnNoneParameter {
int test();
}
//6.有返回值的一参接口
@FunctionalInterface
public interface LambdaSingleReturnSingleParameter {
int test(int n);
}
## 函数式接口引用
1. 调用构造方法
```java
//有参
@FunctionalInterface
interface PersonCreator2 {
Person getPerson(String name, int age);
}
PersonCreator2 creator2 = Person::new;
Person person2 = creator2.getPerson("Fisherman", 18);``
2. 超实例方法引用
语法格式: super::methodName 通过使用super,引用methodName方法的超类版本
同理, 可以捕获this指针. this :: equals 等价于lambda表达式 x -> this.equals(x);
3. 类上实例的方法引用
语法格式:ClassName::methodName
这种方法很不一样, :: 前的类名并不是实例方法的发出者. 真正的发出者是在调用该方法时,作为第一个参数传入方法中.
实现了方法引用的多态性
map、filter的函数式接口定义
```java
@FunctionalInterface
public interface Function<T, R> {
R apply(T t); // 只有这一个未实现的方法
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t); // 只有这一个未实现的方法
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
Optional<Integer> result = Stream.of("f", "ba", "hello")
.map(s -> s.length())
.filter(l -> l <= 3)
.max((o1, o2) -> o1-o2);
// 还原为函数接口的实现方式
Optional<Integer> result2 = Stream.of("fo", "bar", "hello")
.map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return s.length();
}
})
.filter(new Predicate<Integer>() {
@Override
public boolean test(Integer l) {
return l <= 3;
}
})
.max(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});```
Function、Predicate、Comparator 都是函数接口