分类: Java
2022-11-29 11:36:34
if…else…在代码中经常使用,听说可以通过Java 8的Function接口来消灭if…else…!Function接口是什么?如果通过Function接口接口消灭if…else…呢?让我们一起来探索一下吧。
Function接口就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,Function接口可以被隐式转换为 lambda 表达式。可以通过FunctionalInterface注解来校验Function接口的正确性。Java 8允许在接口中加入具体方法。接口中的具体方法有两种,default方法和static方法。
@FunctionalInterface interface TestFunctionService { void addHttp(String url);
} 复制代码
那么就可以使用Lambda表达式来表示该接口的一个实现。
TestFunctionService testFunctionService = url -> System.out.println("http:" + url); 复制代码
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE)
public @interface FunctionalInterface {} 复制代码
2.1.2 说明
上图是FunctionalInterface的注解说明。通过上面的注解说明,可以知道FunctionalInterface是一个注解,用来说明一个接口是函数式接口。 函数式接口只有一个抽象方法。 可以有默认方法,因为默认方法有一个实现,所以不是抽象的。函数接口的实例可以用lambda表达式、方法引用或构造函数引用创建。
FunctionalInterface会校验接口是否满足函数式接口:
编译器会将满足函数式接口定义的任何接口视为函数式接口,而不管该接口声明中是否使用FunctionalInterface注解。
Function接口主要分类:
Function函数的表现形式为接收一个参数,并返回一个值。
3.1.1 源码@FunctionalInterface public interface Function {
R apply(T t); default Function compose(Function super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v));
} default Function andThen(Function super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t));
} static Function identity() { return t -> t;
}
} 复制代码
3.1.2 方法说明
1)apply
测试代码:
public String upString(String str){ Function<String, String> function1 = s -> s.toUpperCase(); return function1.apply(str);
} public static void main(String[] args) { System.out.println(upString("hello!"));
} 复制代码
通过apply调用具体的实现。执行结果:
2)compose
测试代码:
public static void main(String[] args) { Function<String, String> function1 = s -> s.toUpperCase(); Function<String, String> function2 = s -> "my name is "+s; String result = function1.compose(function2).apply("zhangSan"); System.out.println(result);
}
执行结果
如结果所示:compose 先执行function2 后执行function1。
3)andThen
测试代码:
public static void main(String[] args) { Function<String, String> function1 = s -> s.toUpperCase(); Function<String, String> function2 = s -> "my name is "+s; String result = function1.andThen(function2).apply("zhangSan"); System.out.println(result);
} 复制代码
执行结果:
如结果所示:
andThen先执行function1 后执行function2。
测试代码:
public static void main(String[] args) { Stream<String> stream = Stream.of("order", "good", "lab", "warehouse");
Map<String, Integer> map = stream.collect(Collectors.toMap(Function.identity(), String::length));
System.out.println(map);
} 复制代码
执行结果:
Supplier的表现形式为不接受参数、只返回数据。
3.2.1 源码@FunctionalInterface public interface Supplier<T> { /**
* Gets a result.
*
* @return a result
*/ T get();
} 复制代码
3.2.2 方法说明
get:抽象方法。通过实现返回T。
3.2.3 方法举例public class SupplierTest {
SupplierTest(){
System.out.println(Math.random());
System.out.println(this.toString());
}
} public static void main(String[] args) {
Supplier sup = SupplierTest::new;
System.out.println("调用一次");
sup.get();
System.out.println("调用二次");
sup.get();
} 复制代码
执行结果:
如结果所示:Supplier建立时并没有创建新类,每次调用get返回的值不是同一个。
Consumer接收一个参数,没有返回值。
3.3.1 源码@FunctionalInterface public interface Consumer {
void accept(T t);
default Consumer andThen(Consumer super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
} 复制代码
3.3.2 方法说明
public static void main(String[] args) { Consumer<String> consumer = s -> System.out.println("consumer_"+s); Consumer<String> after = s -> System.out.println("after_"+s);
consumer.accept("isReady"); System.out.println("========================");
consumer.andThen(after).accept("is coming");
} 复制代码
执行结果:
如结果所示:对同一个参数T,通过andThen 方法,先执行consumer,再执行fater。
Runnable:Runnable的表现形式为即没有参数也没有返回值。
3.4.1 源码@FunctionalInterface public interface Runnable { public abstract void run();
} 复制代码
3.4.2 方法说明
run:抽象方法。run方法实现具体的内容,需要将Runnale放入到Thread中,通过Thread类中的start()方法启动线程,执行run中的内容。
3.4.3 方法举例public class TestRun implements Runnable { @Override public void run() { System.out.println("TestRun is running!");
}
} public static void main(String[] args) { Thread thread = new Thread(new TestRun());
thread.start();
} 复制代码
执行结果:
如结果所示:当线程实行start方法时,执行Runnable 的run方法中的内容。
Function的主要用途是可以通过lambda 表达式实现方法的内容。
原代码:
@Data public class User { /**
* 姓名
*/ private String name; /**
* 年龄
*/ private int age; /**
* 组员
*/ private List parters;
} public static void main(String[] args) {
User user =new User(); if(user ==null ||user.getAge() <18 ){ throw new RuntimeException("未成年!");
}
} 复制代码
执行结果:
使用Function接口后的代码:
@FunctionalInterface public interface testFunctionInfe { /**
* 输入异常信息
* @param message */ void showExceptionMessage(String message);
} public static testFunctionInfe doException(boolean flag){ return (message -> { if (flag){ throw new RuntimeException(message);
}
});
} public static void main(String[] args) { User user =new User(); doException(user ==null ||user.getAge() <18).showExceptionMessage("未成年!");
} 复制代码
执行结果:
使用function接口前后都抛出了指定的异常信息。
原代码:
public static void main(String[] args) {
User user =new User(); if(user==null){
System.out.println("新增用户");
}else {
System.out.println("更新用户");
}
} 复制代码
使用Function接口后的代码:
public static void main(String[] args) { User user =new User(); Consumer trueConsumer = o -> {
System.out.println("新增用户");
};
Consumer falseConsumer= o -> {
System.out.println("更新用户");
};
trueOrFalseMethdo(user).showExceptionMessage(trueConsumer,falseConsumer);
} public static testFunctionInfe trueOrFalseMethdo(User user){ return ((trueConsumer, falseConsumer) -> { if(user==null){
trueConsumer.accept(user);
}else {
falseConsumer.accept(user);
}
});
} @FunctionalInterface public interface testFunctionInfe { /**
* 不同分处理不同的事情
* @param trueConsumer
* @param falseConsumer
*/ void showExceptionMessage(Consumer trueConsumer,Consumer falseConsumer);
} 复制代码
执行结果:
原代码:
public static void main(String[] args) {
String flag=""; if("A".equals(flag)){
System.out.println("我是A");
}else if ("B".equals(flag)) {
System.out.println("我是B");
}else if ("C".equals(flag)) {
System.out.println("我是C");
}else {
System.out.println("没有对应的指令");
}
} 复制代码
使用Function接口后的代码:
public static void main(String[] args) { String flag="B"; Map<String, Runnable> map =initFunctionMap(); trueOrFalseMethdo(map.get(flag)==null).showExceptionMessage(()->{ System.out.println("没有相应指令");
},map.get(flag));
} public static Map<String, Runnable> initFunctionMap(){ Map<String,Runnable> result = Maps.newHashMap();
result.put("A",()->{System.out.println("我是A");});
result.put("B",()->{System.out.println("我是B");});
result.put("C",()->{System.out.println("我是C");}); return result;
} public static testFunctionInfe trueOrFalseMethdo(boolean flag){ return ((runnable, falseConsumer) -> { if(flag){
runnable.run();
}else {
falseConsumer.run();
}
});
} 复制代码
执行结果:
Function函数式接口是java 8新加入的特性,可以和lambda表达式完美结合,是非常重要的特性,可以极大的简化代码。