函数式接口
函数式接口定义
函数式接口:有且仅有一个抽象方法,可以有多个非抽象方法的接口。
Java为函数式接口引入了一个注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当接口不符合函数式接口定义的时候,编译器会报错。
@FunctionalInterface是一个可选注解,就算不写这个注解,只要保证满足接口只有一个抽象方法,也照样是函数式接口,但是,建议加上该注解。
自定义函数式接口样例:
@FunctionalInterface
public interface MyFunctionInterface {
void duRun();
}
public class Main {
public void run(MyFunctionInterface myFunctionInterface){
myFunctionInterface.duRun();
}
public static void main(String[] args) {
Main main = new Main();
main.run(() -> System.out.println("run myFunctionInterface"));
}
}
函数式接口使用场景
1. 函数式接口作为方法的参数
如果方法的参数是一个函数式接口,我们可以用Lambda表达式作为参数传递,上述的例子正是将函数式接口作为方法的参数使用。再例如线程中的Runnable接口:
public class Main {
// 函数式接口作为方法的参数
public void run(Runnable runnable) {
new Thread(runnable).start();
}
public static void main(String[] args) {
Main main = new Main();
main.run(() -> System.out.println("do runnable"));
}
}
2. 函数式接口作为方法的返回值
如果一个方法的返回值是一个函数式接口,我们可以把一个Lambda表达式作为结果返回
@FunctionalInterface
public interface MyFunctionInterface {
void duRun(int a, int b);
}
public class Main {
// 函数式接口作为方法的返回值
public MyFunctionInterface run() {
return (a, b) -> System.out.println("a-b = " + (a - b));
}
public static void main(String[] args) {
Main main = new Main();
MyFunctionInterface functionInterface = main.run();
// 执行函数式接口
functionInterface.duRun(5, 3);
}
}
常用的函数式接口
常用的函数式接口主要分为四类:
- Supplier接口:生产者,不接收参数,返回对应的数据
- Consumer接口:消费者,接收参数,不返回数据
- Predicate接口:对给定的输入参数执行操作,返回一个boolean类型的结果
- Function接口:接收参数并执行对应逻辑,返回逻辑执行完之后的结果
Supplier接口
定义
Supplier只有一个get()方法,不接收参数,返回一个符合预期类型的数据
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
使用
使用supplier实现简单的工厂:
public class Main {
public static void main(String[] args) {
Supplier<Main> supplier = () -> new Main();
System.out.println(supplier.get());
System.out.println(supplier.get());
}
}
Consumer接口
定义
Consumer接口的accept()方法消费一个指定类型的数据,andThen()方法则可以串联多个consumer接口
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
// 可连续执行多个Consumer的accept()
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
使用
输出结果和上面的Supplier使用样例一样,但Consumer通过accept()封装了重复的逻辑:
public class Main {
public static void main(String[] args) {
Consumer<Main> consumer = (main) -> System.out.println(main);
consumer.accept(new Main());
consumer.accept(new Main());
}
}
通过andThen将两个Consumer串联,先执行consumer1再执行consumer2:
public class Main {
public static void main(String[] args) {
Consumer<Main> consumer1 = (main) -> System.out.println(main);
Consumer<Main> consumer2 = (main) -> System.out.println(main.hashCode());
consumer1.andThen(consumer2).accept(new Main());
consumer1.andThen(consumer2).accept(new Main());
}
}
Predicate接口
定义
Predicate接口通过test()接口进行判断,并返回Boolean值,Predicate接口还支持取反,比较,组合判断等
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
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);
}
}
使用
通过Predict接口判断对象是否为null,且nagate()方法可取反:
public class Main {
public static void main(String[] args) {
Predicate<Main> predicate = (main) -> main != null;
System.out.println(predicate.test(new Main()));
System.out.println(predicate.test(null));
System.out.println(predicate.negate().test(null))
}
}
通过and和or组合判断:
public static void main(String[] args) {
Predicate<Main> predicate1 = (main) -> main != null;
Predicate<Main> predicate2 = (main) -> main.getClass().isAssignableFrom(Main.class);
Predicate<Main> predicate3 = (main) -> main.getClass().isAssignableFrom(MyFunctionInterface.class);
System.out.println(predicate1.and(predicate2).or(predicate3).test(new Main()));
}
Function接口
定义
Function接口的apply()方法可以根据一个类型的数据得到另一个类型的数据,andThen则也可以
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
// 组合函数,先应用before函数
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
// 组合函数,后应用after函数
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;
}
}
使用
使用compose,andThen组合三个函数:
public class Main {
public static void main(String[] args) {
Function<List<String>, List<String>> function = (list) -> {
list.add("function");
return list;
};
Function<List<String>, List<String>> before = (list) -> {
list.add("before");
return list;
};
Function<List<String>, List<String>> after = (list) -> {
list.add("after");
return list;
};
// 输出[before, function, after]
System.out.println(function.compose(before).andThen(after).apply(new ArrayList<>()));
}
}