使用FunctionalInterface优雅的链式编程
函数式接口简介
日常开发中接口是必不可少的一种java类,经常用来提取业务用的各种抽象方法。java8又加入了default默认方法。接口可以视为模板,通过具体业务类实现接口将抽象的方法具体化。函数式接口是一类接口的统称:
只有一个抽象方法
的接口称作函数式接口
,允许有多个默认或静态方法,并使用注解@FunctionalInterface
来标识接口
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
ps:这个注解只是标注一下,不加注解也完全不影响
java.util.function包中已经封装好了常用的一些函数式接口,直接拿来用就好了,当然啦对于强迫症晚期的我就是看接口里定义的方法名有些很不顺眼,还是自己封装爽啊
下面就是java8里封装好的一些接口了
看着一大堆接口,其实仔细看看只有4个基本接口,其他的都是基于这4个扩展的,无非就是多个参数,固定返回值啥的,具体的自己扒拉吧
四个基本类:
Consumer(消费型),Supplier(生产型),Function(功能性),Predicate(断言型)
1. Consumer 消费型函数接口
name | type | method | description |
---|---|---|---|
Consumer | Consumer<T> | void accept(T t); | 消费型函数accept,没有返回值; |
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
// 使用示例:
// consumer(123, System.out::println); 123
public static void consumer(int num, Consumer<Integer> consumer) {
consumer.accept(num);
}
// andthen(3,it->System.out.println(it+=1),it->System.out.println(it+=3)); 4 6
public static void andthen(int num, Consumer<Integer> consumer1, Consumer<Integer> consumer2) {
// consumer1.accept(num);
// consumer2.accept(num);
consumer1.andThen(consumer2).accept(num);
}
2.Supplier 供给型函数接口
name | type | method | description |
---|---|---|---|
Supplier | Supplier<T> | T get(); | 生产型接口get,不接受参数,返回实体对象 |
@FunctionalInterface
public interface Supplier<T> {
T get();
}
// 使用示例:
// supplierGet(() -> 3); 3
public static int supplierGet(Supplier<Integer> supplier) {
return supplier.get();
}
3.Predicate 断言函数接口
name | type | method | description |
---|---|---|---|
Predicate | Predicate<T> | boolean test(T t); | boolean型接口test,接收对象,返回真或假 |
@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);
}
}
// 使用示例:
// predicateAnd("Hello World!",str->str.contains("!"),str->str.length()<5) true
public static boolean predicateAnd(String str, Predicate<String> p1, Predicate<String> p2) {
// p1.test(str) && p2.test(str);
return p1.and(p2).test(str);
}
// predicateOr("avbgh!",str->str.contains("N"),str->str.contains("S")) false
public static boolean predicateOr(String str, Predicate<String> p1, Predicate<String> p2) {
// p1.test(str) || p2.test(str);
return p1.or(p2).test(str);
}
// predicate(55, num -> num < 50) false
public static boolean predicate(int num, Predicate<Integer> it) {
// !it.test(num);
return it.test(num);
}
4.Function 功能函数接口
name | type | method | description |
---|---|---|---|
Function | Function<T,R> | R apply(T t); | 功能型函数apply,接收参数T,返回R; |
@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;
}
}
// 使用示例:
// fun(1,value->2*value) 2
// value * 2 => 1*2 = 2
public static int fun(int num, Function<Integer,Integer> function){
return function.apply(num);
}
// 倒序执行
// fun(3,value->value * 3,value->value*value)
// (value*value) * 3 => 3*3*3 = 27
public static int fun(int num, Function<Integer,Integer>f1,Function<Integer,Integer> f2){
// f2=> f1
return f1.compose(f2).apply(num);
}
// 顺序执行
// fun(3,value->value * 3,value->value*value)
// (value*3) * (value*value) => (3*3)*(3*3) = 81
public static int fun(int num, Function<Integer,Integer> f1,Function<Integer,Integer> f2){
// f1=> f2
return f1.andThen(f2).apply(num);
}
函数接口实战
到此相信大家对于FunctionalInterface的几个基本常用类的定义和使用已经基本了解了。简单来说,
接口本身是不承载计算逻辑的,它更像一个模板公式,你传给它什么运算逻辑它就执行什么,并且支持lambd表达式
。
实战开撸~~
1.定义几个函数接口
@FunctionalInterface
public interface BranchHandle {
/**
* 分支操作
* @param trueHandle 为true时要进行的操作
* @param falseHandle 为false时要进行的操作
* @return void
**/
void then(Runnable trueHandle, Runnable falseHandle);
}
@FunctionalInterface
public interface Formatter {
String format(String val);
}
@FunctionalInterface
public interface BlankHandler<T> {
//accept
/**
* 值不为空时执行消费操作
* 值为空时执行其他的操作
* @param action 值不为空时,执行的消费操作
* @param emptyAction 值为空时,执行的操作
* @return void
**/
void then(Consumer<? super T> action, Runnable emptyAction);
}
@FunctionalInterface
public interface TrueHandler<T> {
//accept
/**
* 值不为空时执行消费操作
* 值为空时执行其他的操作
* @param action 值不为空时,执行的消费操作
* @return void
**/
void then(Consumer<? super T> action);
}
@FunctionalInterface
public interface ExceptionHandler {
/**
* 抛出异常信息
* @param msg 异常信息
* @return void
*/
void then(String msg);
}
2.制作个工具类测试下
public class LFUtils {
/**
* 常用类型判空
* @param t
* @param <T>
* @return
*/
public static <T> boolean isEmpty(T t){
boolean ret = false;
if(t == null){
ret = true;
}else if(t instanceof String){
String tart = (String)t;
ret = predicateTest(tart, it-> it.length() == 0);
}else if(t instanceof Collection){
Collection tart = (Collection)t;
ret = predicateTest(tart, it-> it.size() == 0);
}else if(t instanceof Object[]){
Object[] tart = (Object[])t;
ret = predicateTest(tart, it-> it.length == 0);
}
return ret;
}
/**
* 为false返回
* @param t
* @param <T>
* @return
*/
public static <T> boolean isNotEmpty(T t){
return !isEmpty(t);
}
//Predicate
public static <T> boolean predicateTest(T num, Predicate<T> it) {
return it.test(num);
}
/**
* 参数为true或false时,分别进行不同的操作
* @param b
* @return ranchHandle
**/
public static BranchHandle isTureOrFalse(boolean b){
return (trueHandle, falseHandle) -> {
if (b){
trueHandle.run();
} else {
falseHandle.run();
}
};
}
/**
* 如果为false则抛出异常
* @param t
* @return ExceptionHandler
*/
public static <T> ExceptionHandler<String> checkEx(T t){
return (errorMsg) -> {
if(isEmpty(t)) {
throw new RuntimeException(errorMsg);
}
};
}
/**
* 为true或false时,分别进行不同的操作
* @param t
* @return BlankHandler
**/
public static <T> BlankHandler<T> checkEmpty(T t){
return (consumer, runnable) -> {
if (isEmpty(t)){
runnable.run();
} else {
consumer.accept(t);
}
};
}
/**
* 为true返回
* @param t
* @return TrueHandler
**/
public static <T> TrueHandler<T> isNotBlank(T t){
return (s) -> {
if (!isEmpty(t)){
s.accept(t);
}
};
}
/**
* 为false返回
* @param t
* @return TrueHandler
**/
public static <T> TrueHandler<T> isBlank(T t){
return (s) -> {
if (isEmpty(t)){
s.accept(t);
}
};
}
/**
* 自定义函数计算
* @param t
* @param function
* @param <T>
* @return
*/
public static <T,U> U compute(T t, Function<T,U> function){
return function.apply(t);
}
public static void main(String[] args){
//VUtils.isTrue(1==1).then("出现异常了");
LFUtils .isTureOrFalse(1==1).then(()->{
log.info("==结果为true==");
},()->{
log.info("==结果为false==");
});
LFUtils .checkBlank("aaaa").then(System.out::println,()->{
log.info("==空值==");
});
LFUtils .checkBlank(new ArrayList<>()).then((r)->{
log.info("==checkBlankArray===",r);
},()->{
log.info("==checkBlankArray===");
});
}
}
似不似很简洁,似不似很优雅,当然啦,好用归好用,过度使用就不好玩了。使用太多对代码调试还是有影响的,尤其是复杂业务中,debug可能会变成“跳跳强”哦~