函数式接口
1.基本概念
有且仅有一个抽象方法的接口
函数式接口,即适用于函数式编程场景的接口。而Java中的函数是编程体现就是Lambda,所以函数式接口是可以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利进行推导
语法格式:
修饰符 interface 接口名称{
public abstract 返回值类型 方法名称(可选参数信息);
}
@FunctionalInterface注解
作用:可以检测接口是否是一个函数式接口
2.函数式接口的使用
一般可以作为方法的参数和返回值
public class Demo01 {
//定义一个方法,参数适用函数是接口MyFunctionalInterface
public static void show(MyFuncitionalInterface myInter){
myInter.method();
}
public static void main(String[] args) {
//调用show方法,方法的参数是一个接口,所以可以传递接口的实现类对象
show(new MyFunctionalInterfaceImpl());
//调用show方法,方法的参数是一个接口,所以我们可以传递接口的匿名内部类
show(new MyFuncitionalInterface() {
@Override
public void method() {
System.out.println("使用匿名内部类");
}
});
//调用show方法,方法的参数是一个函数式接口,可以使用Lambda表达式
show(()->{
System.out.println("使用Lambda重写接口中的抽象方法");
});
}
}
3.函数式编程
public class Demo02 {
public static void showLog(int level,MessageBuilder mb){
if(level==1){
System.out.println(mb.builderMessage());
}
}
public static void main(String[] args) {
String msg1="hello";
String msg2="world";
String msg3="Java";
showLog(1,()->{
return msg1+msg2+msg3;
});
showLog(2,()->{
return msg1+msg2+msg3;
});
}
}
使用Lambda表达式作为参数仅仅是把参数传递到showLog方法中,只有满足条件,才会调用MessageBuilder方法中的builderMessage方法
如果条件不满足,那么MessageBuilder方法中的builderMessage方法不会执行,不会存在性能的浪费
使用Lambda作为参数
public class Demo03 {
public static void startThread(Runnable run){
new Thread(run).start();
}
public static void main(String[] args) {
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
//Lambda表达式
startThread(()->{
System.out.println(Thread.currentThread().getName());
});
}
}
使用Lambda作为返回值
public class Demo04 {
public static Comparator<String> getComparator(){
return(String o1,String o2)->{
return o2.length()-o1.length();
};
}
public static void main(String[] args) {
String[] arr={
"Kobe","James","Curry","Jordan"};
Arrays.sort(arr,getComparator());
System.out.println(Arrays.toString(arr));
}
}
4.常用函数式接口
Supplier接口
T get():用来获取一个泛型参数指定类型的对象数据
public class Demo05 {
//定义一个方法,方法的参数传递Supplier<T>接口,泛型执行String.get方法返回一个String
public static String getString(Supplier<String> sup){
return sup.get();
}
public static void main(String[] args) {
//调用getString方法,方法的参数Supplier是一个函数式接口,所以可以传递Lambda表达式
String s=getString(()->{
return "hello,world";
});
System.out.println(s);
}
}
Consumer接口
抽象方法:void accept(T t),意为消费一个指定泛型的数据
public class Demo06 {
public static void method(String s, Consumer<String> con){
con.accept(s);
}
public static void main(String[] args) {
//调用method方法,传递字符串,方法的另一个参数是Consumer接口,是一个函数式接口,可以使用Lambda表达式
method("Kobe",(String s)->{
System.out.println(s);
});
}
}
默认方法:andThen 如果一个方法的参数和返回值全部都是Consumer类型,那么就可以实现效果:消费数据的时候,首先做一个操作,然后再做一个操作,实现组合
public class Demo06 {
//定义一个方法,方法的参数传递一个字符串和两个Consumer接口,Consumer接口的泛型使用字符串
public static void method(String s,Consumer<String> con1,Consumer<String> con2){
/* con1.accept(s);
con2.accept(s);不使用andThen*/
con1.andThen(con2).accept(s);
}
public static void main(String[] args) {
method("hello",(t)->{
System.out.println(t.toUpperCase());
},(t)->{
t.toLowerCase();
});
}
}
Predicate接口
对某种类型的数据进行判断
抽象方法:boolean test(T t)
public class Demo06 {
public static boolean method(int num, Predicate<Integer> pre){
return pre.test(num);
}
public static void main(String[] args) {
int num=20;
boolean res = method(num, (Integer n) -> {
return n>10;
});
System.out.println(res);
}
}
默认方法and,or,negate
public class Demo06 {
/*
判断字符串长度是否大于5,字符串中是否包含a
*/
public static boolean method(String s,Predicate<String> pre1,Predicate<String> pre2){
return pre1.and(pre2).test(s);
//return pre1.or(pre2).test(s);
}
public static void main(String[] args) {
String s="HelloWorld";
boolean res = method(s, (String str) -> {
return str.length() > 5;
}, (String str) -> {
return str.contains("a");
});
System.out.println(res);
}
}
练习
public class Demo07 {
public static ArrayList<String> method(String[] arr, Predicate<String> pre1,Predicate<String> pre2){
ArrayList<String> list=new ArrayList<>();
for (String s : arr) {
boolean b = pre1.and(pre2).test(s);
if(b){
list.add(s);
}
}
return list;
}
public static void main(String[] args) {
String[] arr={
"Kobe,24","James,23","Jordan,23","Curry,30"};
ArrayList<String> list = method(arr, (String s) -> {
return s.split(",")[1].equals("23");
}, (String s) -> {
return s.split(",")[0].length() > 5;
});
System.out.println(list);
}
}
Function接口
接口用来根据一个类型的数据得到另一个类型的数据
抽象方法:R apply(T t),根据T的参数获取类型R的结果
public class Demo08 {
public static void method(String s, Function<String,Integer> fun){
Integer in=fun.apply(s);
System.out.println(in);
}
public static void main(String[] args) {
String s="12345";
method(s,(String str)->{
return Integer.parseInt(str);
});
}
}