什么是函数式接口
只有一个必须被重写的抽象方法的接口
@FunctionalInterface 注解强制检测是否为函数式接口
为什么使用函数式接口
当重写函数式接口的方法后,发现,这个方法中执行逻辑相同,只有判断规则不同,就把判断规则抽取出来,自己定义,提高代码复用性
代码举例:
//在类的尖括号中 表示需要的泛型个数 ,T和R两种泛型
@FunctionalInterface
interface Class003_TestLambda<T,R> {
//返回值类型是提供的 R 泛型,提供的两个参数类型一致为 T类型
public R getR(T t,T r);
}
用Lambda表达式使用函数式接口
lambda表达式的使用
class TestLambda001{
public static void main(String[] args) {
//2:调用定义的方法,传递参数,第三个直接传递lambda表达式,使用表达式中规则
System.out.println(getAdd(1L, 2L, (a,b)-> a<<b));
}
//1:定义一个方法,传递需要计算的两个参数,在传递函数式接口类型,表示使用自定义规则【注意在接口尖括号中定义泛型的具体类型,如果不定义具体类型,默认为object】,泛型只能定义为引用类型
//第一个泛型Long 表示T类型【T是方法中参数列表】, 第二个Long类型 表示R类型【R是方法使用后的返回值】
public static long getAdd(Long l1,Long l2,Class003_TestLambda<Long,Long> testLambda001){
return testLambda001.getR(l1,l2);
}
}
每一步解析如何调用执行
/* 1: System.out.println(getAdd(1L, 2L, (a,b)-> a<<b));
调用getAdd方法,传递了三个参数,long类型的1和2,和接口实现类的lambda表示式
2:public static long getAdd(Long l1,Long l2,Class003_TestLambda<Long,Long> testLambda001)
接收参数,执行方法体内容,参数列表中,Class003_TestLambda类型需要在尖括号中指定泛型,具体的类型表示这个接口的泛型代表的类型【T为 Long类型,R为 Long两个类型】
3:执行方法体代码 testLambda001.getR(l1,l2)
会调用接口中被重写的方法【就是lambda表达式内容】,参数类型为两个 T的泛型,在第二步方法生命部分已经指定,T为Long类型,R也为Long类型
4:执行lambda表达式 (a,b)-> a<<b
参数a和b:就是testLambda001.getR(l1,l2)这里传递的参数,l1和l2两个值
然后执行a<<b,得到结果返回
*/
jdk中的四大内置函数式接口
内置函数式接口作用
当你需要写一个方法,方法中有一段代码规则或者逻辑不固定,为了提高方法的复用【灵活性】,将判断规则或者逻辑放在外面,交由执行的时候具体在定义,
这时候需要一个函数式接口,可以直接使用内置的符合需要的函数式接口
内置函数式接口代码使用Demo
/*
java.util.function 包下提供了一系列的函数式接口
四大内置函数式接口 :
Consumer<T> 消费型接口【接收一个泛型类型的参数,没有返回值的函数式接口】
void accept(T t) 对给定的参数执行此操作。
Function<T,R> 函数型接口
R apply(T t) 将此函数应用于给定的参数。
Supplier<T> 供给型接口
T get() 获取结果。
Predicate<T> 段言型接口
boolean test(T t) 根据给定的参数计算此谓词。
*/
public class Class001_FunctionalInterface {
public static void main(String[] args) {
testComsumer(5000,m-> System.out.println("为主播打赏消费"+m));
testComsumer(10000,m-> System.out.println("今天做全身spa消费"+m));
System.out.println(strHandler(" 哈哈 ",s->s.trim()));
System.out.println(strHandler(" abc ",s->s.toUpperCase()));
//[5,10]
System.out.println(testNumRandom(5,()->(int)(Math.random()*(10-5+1)+5)));
System.out.println(testNumRandom(10,()->(int)(Math.random()*(20-10+1)+10)));
System.out.println(testString(List.of("张三","李四","张三丰","欧阳王渊"),s->s.length()>=3));
}
//对一个集合中的多个字符串进行某种规则的过滤,返回过滤后的结果
public static List<String> testString(List<String> list, Predicate<String> pre){
//定义一个List集合,存储满足条件的字符串
List<String> strs = new ArrayList<>();
//遍历原list集合,拿到每一个字符串进行判定
for(String s :list){
//满足条件字符串放入strs集合
if(pre.test(s)){
strs.add(s);
}
}
return strs;
}
//功能: 提供指定个数的,指定规则的随机整数
//定义方法: 1)需求 2)参数: 不确定的数据|有可能会改变的数据定义参数列表上 3)返回值: 方法执行完毕是否需要得到一个结果,需要定义返回值 4)方法名 : 见名知意
public static List<Integer> testNumRandom(int num, Supplier<Integer> sup){
//定义一个List集合,存储生成的随机数
List<Integer> list = new ArrayList<>();
//循环num次,每次调用get方法生成一个随机数
for(int i=1;i<=num;i++){
list.add(sup.get());
}
//返回结果
return list;
}
//功能: 对一个字符串进行某种行为的操作得到结果
public static String strHandler(String str, Function<String,String> fun){
return fun.apply(str);
}
//功能: 每天的缴费记录
public static void testComsumer(double money, Consumer<Double> con){
con.accept(money);
}
}