- 1、函数式接口的定义
- 2、FunctionalInterface注解
- 3、函数式接口的使用
- 4、lambda延迟执行特性
- 5、Supplier函数式接口
- 6、Consumer函数式接口
- 7、Predicate函数式接口
- 8、Function函数式接口
1、函数式接口的定义
有且仅有一个抽象方法的接口
函数式接口顾名思义就是函数式编程的接口,在Java中最能体现函数式编程的无非就是Lambda,所以函数式接口是可以适用于Lambda使用的接口;
只有确保只有一个抽象方法,Lambda才能顺利地推导
2、FunctionalInterface注解该注解与Override注解类似,FunctionalInterface用来检测该接口是否是一个函数式接口(只有一个抽象方法)
被@FunctionalInterface注解标记的类型表明这是一个函数接口。从概念上讲,函数接口只有一个抽象方法。如果接口声明的抽象方法覆写Object类的公共方法,那这方法不算作接口的抽象方法,因为接口具有Object方法的默认实现。
3、函数式接口的使用首先定义一个函数式接口
@FunctionalInterface
public interface MyFunctionInterface {
public abstract void method();
}
(1)第一种使用方式(实现接口)
重写接口
在testFun方法参数中定义接口
调用时传入它的实现类
public class MyFunctionInterfaceImpl implements MyFunctionInterface{
@Override
public void method() {
System.out.println("第一种函数式接口的使用方式...");
}
}
public class TestFunctionInterface {
public static void testFun(MyFunctionInterface myFunctionInterface) {
myFunctionInterface.method();
}
public static void main(String[] args) {
testFun(new MyFunctionInterfaceImpl());
}
}
(2)内名内部类
testFun(new MyFunctionInterface() {
@Override
public void method() {
System.out.println("第二种实现方式...");
}
});
(3)Lambda表达式
testFun(()->{
System.out.println("第三种实现方式");
});
或者
testFun(()-> System.out.println("第三种实现方式"));
4、lambda延迟执行特性
使用一个日志案例来演示
public class lambdaLater {
public static void log(int k, String msg) {
if (k == 1) {
System.out.println(msg);
}
}
public static void main(String[] args) {
String msg1 = "aa";
String msg2 = "bb";
String msg3 = "cc";
log(2, msg1 + msg2 + msg3);
}
}
根据上文代码,如果传入的k=2,那么日志不会打印,但是msg1 + msg2 + msg3已经完成了拼接,这样就会浪费性能。
❤️ 经过lambda优化
使用lambda之前,首先需要定义一个函数式接口。
@FunctionalInterface
public interface LambdaLaterInterface {
public abstract String printMsg();
}
测试
public class lambdaLater {
public static void log2(int k, LambdaLaterInterface lambdaLaterInterface) {
if (k == 1) {
System.out.println(lambdaLaterInterface.printMsg());
}
}
public static void main(String[] args) {
String msg1 = "aa";
String msg2 = "bb";
String msg3 = "cc";
log2(2, () -> {
System.out.println("------");
return msg1 + msg2 + msg3;
});
}
}
结果如下
没有“-------”,说明字符串没有进行拼接。
5、Supplier函数式接口
@FunctionalInterface public interface Supplier{ T get(); }
根据Supplier源代码可以看出,Supplier接口中是一个无参的的抽象方法;当你接口泛型指定什么类型,那么T get()抽象方法就会返回什么类型。
所以Supplier被成为生产型接口
public class SupplierDemo {
public static String sup(Supplier supplier) {
return supplier.get();
}
public static void main(String[] args) {
//只有一行代码,省略了return和{}和,
String s = sup(() -> "hello");
System.out.println(s);
}
}
public class SupplierDemo {
public static int getMax(Supplier sup) {
return sup.get();
}
public static void main(String[] args) {
int[] nums = {1, 3, 5, 0, 9};
int maxNum = getMax(() -> {
int max = nums[0];
for (int temp : nums) {
if (temp > max)
max = temp;
}
return max;
});
System.out.println(maxNum);
}
}
6、Consumer函数式接口
@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); }; } }
这个Consumer接口刚好和Supplier接口的作用相反,如果接口泛型定义了什么类型,那么方法accept就可以消费什么类型;
Consumer是一个典型的消费型接口
public class ConsumerDemo {
public static void strRev(String str, Consumer con) {
con.accept(str);
}
public static void main(String[] args) {
strRev("test", (temp) -> {
String result = new StringBuilder(temp).reverse().toString(); //反转字符串
System.out.println(result);
});
}
}
在Consumer接口中,有一个默认的方法andThen
这个andThen方法的作用是对两个Consumer接口进行连接消费
default ConsumerandThen(Consumer super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; }
public class ConsumerDemo {
public static void strRev(String str, Consumer consumer, Consumer consumer2) {
consumer.andThen(consumer2).accept(str);
}
//进行组合消费
strRev("hello",
(name) -> {
System.out.println(name.toLowerCase());
},
(name2) -> {
System.out.println(name2.toUpperCase());
});
}
}
7、Predicate函数式接口
源代码中包含了一个抽象方法test和四个默认方法
@FunctionalInterface public interface Predicate{ boolean test(T t); //抽象方法 //逻辑与 default Predicate and(Predicate super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } //逻辑否 default Predicate negate() { return (t) -> !test(t); } //逻辑或 default Predicate or(Predicate super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } //比较两个对象是否相等 static Predicate isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); } }
public class PredicateDemo {
public static boolean predicate(int a, Predicate predicate) {
return predicate.test(a);
}
public static void main(String[] args) {
boolean flag = predicate(6, (num) -> {
return num > 5;
});
System.out.println(flag);
}
}
and方法的用法,与&&等同
public class PredicateDemo {
public static boolean predicate2(int a, Predicate pre, Predicate pre2) {
return pre.and(pre2).test(a);
}
public static void main(String[] args) {
boolean flag2 = predicate2(6,
(num) -> {
return num > 2;
},
(num2) -> {
return num2 > 8;
});
System.out.println(flag2);
}
}
or方法和and方法类似,与||等同。
negate方法,与!(取反)等同。
8、Function函数式接口
andThen方法的应用
在fun的基础上,fun2在进行加20,结果等于42;
public static Integer function2(String s, Functionfun, Function fun2) { return fun.andThen(fun2).apply(s); } public static void main(String[] args) { Integer a = function2("12", (num) -> { return Integer.valueOf(num) + 10; }, (num)->{ return num + 20; }); System.out.println(a); }



