天天看点

java 函数接口_java中的函数式接口

是什么??

有且只有一个抽象方法的接口

场景:

适用于函数式编程场景(使用lambda表达式编程)的接口,函数式接口可以适用于lambda使用的接口。

只有确保接口中有且只有一个抽象方法,java中的lambda才能顺利推到

格式

@FunctionalInterfacepublic interfaceMyInterface {//定义一个抽象方法

public abstract voidmethod();//void method2();

}

函数式接口的使用:

Lambda作为参数

例如:

public classDemo {public static voidshow(MyInterface myInterface){

myInterface.method();

}public static voidmain(String[] args) {//调用show方法,方法的参数是一个接口,所以可以传递接口的实现类对象

show(newMyInterfaceImp());//调用show方法,方法的参数是一个接口,所以可以传递接口的匿名内部类

show(newMyInterface() {

@Overridepublic voidmethod() {

System.out.println("使用匿名内部类重写接口的抽象方法");

}

});//调用show方法,方法的参数是一个函数式接口,所以,我们可以使用lambda表达式

show(()->{

System.out.println("使用lambda表达式重写接口中的抽象方法");

});//简化lambda表达式

show(()-> System.out.println("简化lambda表达式"));

}

注意:使用匿名内部类回生成.class文件,但是lambda表达式不会,减少JVM的加载

结果:

java 函数接口_java中的函数式接口

函数式编程

Lambda的延迟执行减少性能浪费:

例子:

public classDemo01Logger {public static void showLog(intlevel,String msg){if (level == 1){

System.out.println(msg);

}

}public static voidmain(String[] args) {

String msg1= "AAA";

String msg2= "BBB";

String msg3= "CCC";

showLog(1,msg1+msg2+msg3);

}

}

利用lambda表达式优化:

1先定义一个函数式接口

@FunctionalInterfacepublic interfaceMessageBuilder {//定义拼接消息的抽象方法,返回拼接完成的消息

public abstractString builderMsg();

}

public classDemo02Logger {//显示日志方法,

public static void showLog(intlevel,MessageBuilder messageBuilder){if (level == 1){

System.out.println(messageBuilder.builderMsg());

}

}public static voidmain(String[] args) {

String msg1= "AAA";

String msg2= "BBB";

String msg3= "CCC";//调用showLog方法,参数MessageBuilder式一个函数式接口,可以传递Lambda表达式

showLog(1,()->{//返回一个拼接好的字符串

System.out.println("有没有拼接");return msg1+msg2+msg3;

});

}

}

可以通过改变日志级别,看看输出存不存在"有没有拼接"

Lambda作为参数和返回值

public classDemo03Runable {//定义一个方法startThread 方法参数使用函数式接口Runnable

public static voidstartThread(Runnable runnable){newThread(runnable).start();

}public static voidmain(String[] args) {//匿名内部类实现

startThread(newRunnable() {

@Overridepublic voidrun() {

System.out.println(Thread.currentThread().getName()+"线程启动了");

}

});//因为Runnable接口是一个函数式接口,里面只有一个抽象方法run方法,可以使用lambda表达式

startThread(()->{

System.out.println(Thread.currentThread().getName()+"lambda线程启动了");

});

startThread(()->System.out.println(Thread.currentThread().getName()+"优化lambda线程启动了"));

}

}

Lambda作为返回值

public classDemo02Comparator {//定义一个方法,方法的返回值位函数式接口Comparator

public static ComparatorgetComparator(){//方法返回值式一个接口,返回接口的匿名内部类

return new Comparator() {

@Overridepublic intcompare(String o1, String o2) {//安装字符串降序排序

return o1.length() -o2.length();

}

};

}public static ComparatorgetComparator2() {//方法返回值式一个函数式接口,返回接口的lambda表达式

return (String o1, String o2)->{return o1.length() -o2.length();

};

}//优化表达式

public static ComparatorgetComparator3() {//方法返回值式一个函数式接口,返回接口的lambda表达式

return ( o1, o2)-> o1.length() -o2.length();

}public static voidmain(String[] args) {

String[] arr= {"AAAAAAA","BBBB","CCCCCCC"};

System.out.println(Arrays.toString(arr));//对数组进行拍寻

Arrays.sort(arr,getComparator());

System.out.println(Arrays.toString(arr));

}

}

常用的函数式接口:

Supplier接口:

java.util.function.Supplier 接口包含一个无参方法:T get()

作用:用来获取一个泛型参数指定类型的对象数据。

对应的lambda表达式需要提供一个符合泛型类型的对象数据

public classDemo01Supplier {//方法参数传递Supplier接口,泛型String,get返回一个String

public static String getString(Suppliersupplier){returnsupplier.get();

}public static voidmain(String[] args) {//调用getString方法。使用lambda表达大师

String s = getString(()->{return "生成字符串";

});//优化表达式

String s1 = getString(()->"优化生成字符串");

System.out.println(s);

System.out.println(s1);

}

}

结果:

生成字符串

优化生成字符串

简单练习

答案:

public classDemo02Test {//获取数组元素的最大值,参数位supplier接口,泛型Integer

public static Integer getMax(Suppliersupplier){returnsupplier.get();

}public static voidmain(String[] args) {//定义数组

int[] arrint = {111,222,444,333};int maxinarr =getMax(()->{int max = arrint[0];for (inti : arrint) {if(i>max){

max=i;

}

}returnmax;

});

System.out.println(maxinarr);

}

}

Consumer

public classDemo03Consumer {public static void method(String name, Consumerconsumer){

consumer.accept(name);

}public static voidmain(String[] args) {//因为accept有参数,所以lambda表达式需要加入参数。

method("quanzhiqiang",(String name)->{

System.out.println(name);

String reName= newStringBuffer(name).reverse().toString();

System.out.println(reName);

});

}

}

结果:

quanzhiqiang

gnaiqihznauq

Consumer中的默认方法 andThen

public classDemo4Consumer {public static void method(String str , Consumer co1,Consumerco2){

co1.accept(str);

co2.accept(str);

}public static void method1(String str , Consumer co1,Consumerco2){

co1.andThen(co2).accept(str);//执行co1再执行co2,比上面的要简洁一些

}public static voidmain(String[] args) {

method1("quan",

(t)->{//lambda表达式参数的类型,可以省略

System.out.println(t.toUpperCase());

},

(t)->{

System.out.println(t.toLowerCase());

});

}

}

练习:

public classDemo5Consmer {public static void pringinfo(String[] arr , Consumer c1,Consumerc2){for(String s : arr) {

c1.andThen(c2).accept(s);

}

}public static voidmain(String[] args) {

String[] arr= {"AA,N","BB,M","CC,N"};

pringinfo(arr,

( msg)->{//对字符串进行分割,取出姓名

String name = msg.split(",")[0];

System.out.print("姓名:"+name);

},

(msg)->{//对字符串进行分割,取出性别

String sex = msg.split(",")[1];

System.out.println("性别:"+sex);

});

}

}

Predicate接口

public classPredicateTest {//定义方法,参数传递一个字符串,Predicate接口

public static boolean checkString(String s, Predicatepred){returnpred.test(s);

}public static voidmain(String[] args) {

String s="ABCD";

System.out.println(checkString(s,(ss)->{if (ss.length()>5){return true;

}else{return false;

}

})

);

}

}

接口中的默认方法,and  or negate:

public classPredicateT {public static boolean checkString(String s, Predicate p1, Predicatep2){//return p1.test(s) && p2.test(s);

return p1.and(p2).test(s);//等价于上面//return p1.or(p2).test(s);//或//return p1.negate().test(s)//negate非

}public static voidmain(String[] args) {

String s= "anbced";boolean re =checkString(s,

(ss)->{return ss.length()>5;

},

(ss)->{return ss.contains("a");

});

System.out.println(re);

}

}

练习:

public classPredicateTest2 {private static void xuanze(String[] arr, Predicate pre1, Predicatepre2){

List stringList =new ArrayList<>();for(String s : arr) {if(pre1.and(pre2).test(s)){

stringList.add(s);

}

}

System.out.println(stringList);

}public static voidmain(String[] args) {

String[] arr= {"1111,N","222,M","44444","N"};

xuanze(arr,

(s)->{return s.split(",")[0].length()==4;

},

(s)->{return s.split(",")[1].equals("N");

});

}

}

Function接口

public classFunctionDemo {public static void exchange(String s, Functionfunction){

Integer i=function.apply(s);//int i1 = function.apply(s);自动拆箱,将Integer类型自动拆成Int类型

System.out.println(i);

}public static voidmain(String[] args) {

String si= "123";

exchange(si,(ss)->{returnInteger.parseInt(ss);

});//优化//exchange(si,(ss)-> Integer.parseInt(ss)//);

}

}

默认方法andThen

public classFunctionDemo2_andThen {private static void change(String s,Function f1,Functionf2){

String ss=f1.andThen(f2).apply(s);

System.out.println(ss);

}public static voidmain(String[] args) {

String s= "123";

change(s,

(s1)->{//把字符串转整数

return Integer.parseInt(s1)+10;

},

(i)->{return i+"";

});

}

}