java高级:函数式接口

本文探讨了Java中的函数式接口,包括如何判断接口是否为函数式接口,使用FUNCTIONINTERFACE注解,以及它们在方法参数和返回值中的应用。重点讲述了lambda表达式的延迟特性和在日志等级控制中的应用。此外,还介绍了常见的函数式接口,如Supplier、Consumer、Predicate和Function,通过实例展示了这些接口的使用方法和组合操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1什么是函数式接口:

                                

2如何判断函数式接口是否成功创建:使用FUNCTIONINTERFACE注解(使用方法同@override)

                                

3 函数式接口的使用:一般可以作为方法的参数和返回值来使用(在这里重新复习接口内容知识

         1.如果主方法调用的方法,该方法传递进来的参数是一个接口,那么可以:

                1主方法中传入的参数可以是:接口的实现类

                2主方法中传入的参数可以是:接口的匿名内部类

                3如果方法中的参数是函数式接口,则可以使用lambda表达式

package com.bed.hanshushijiekou;
//使用三种方法来调用接口的抽象方法
public class mainfangfa {
    //第一种方法:直接把接口传递进来,然后调用接口中的方法。
    public static void method1(myInterface myinter){
        myinter.method();
    }
    public static void main(String[] args) {
    //第二种方法:调用方法一,然后参数传递接口的实现类
        method1(new myInterfaceimpl());
    //第三种方法。参数传递接口的匿名内部类。
        method1(new myInterface() {
            @Override
            public void method() {
                System.out.println("传递接口的匿名内部类重写接口中的方法");
            }
        });
    //同样是第三种方法使用lambda表达式
        method1(()-> System.out.println("使用lambda表达式传递接口的匿名内部类重写接口中的方法"));
    }
}

                 补充知识点:lambda表达式可以看作是匿名内部类的语法糖。但是lambda表达式省去

                                      了.class文件,所以效率更高

        添加知识点:lambda表达式的延迟性:

        现有如下代码 :

                                

         日志只有传入等级为一级时才显示信息,当传入等级为其他等级时,msg1+msg2+msg3的组

         合操作就是多余的。这时我们可以使用lambda表达式的延时特性来节省资源。避免性能浪费        代码实现:

//创建一个接口里面有一个抽象类方法
package com.bed.hanshushijiekou.demo01;

public interface msgplus {
    public abstract String msgplus();
}

//执行日志
package com.bed.hanshushijiekou.demo01;

public class RiZhishow {
    public static void msgshow(int level,msgplus msg){
        if(level==1){
            System.out.println(msg.msgplus());
        }
    }
    public static void main(String[] args) {
        String msg1="hello";
        String msg2="bed";
        String msg3="java";

        msgshow(2,()->{
            return msg1+msg2+msg3;//重写接口中的抽象方法
        });
    }
}

     1.使用lambda表达式作为方法的参数:(其实上面的方法就是一个大的演示框架,而下面的

                主方法的lambda就相当于往构建好的大框架(接口的实现类)中添加更细致的操作步骤而已)

         如果主方法调用的方法,该方法传递进来的参数是一个接口,那么可以:

                1主方法中传入的参数可以是:接口的实现类

                2主方法中传入的参数可以是:接口的匿名内部类

                3如果方法中的参数是函数式接口,则可以使用lambda表达式

        ​​​​​​​        ​​​​​​​        

代码实现:

package com.bed.hanshushijiekou;

public class ThreadRunable {
    public static void startThread(Runnable r){//参数是Runnable接口
        new Thread(r).start();//开启多线程
    }

    public static void main(String[] args) {
        //方法1传递匿名内部类(老方法)
        startThread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"->"+"线程启动了");
            }
        });
        //方法2使用lambda表达式
        startThread(()->{
            System.out.println(Thread.currentThread().getName()+"->"+"线程启动了");
        });
    }
}

  2.使用lambda表达式作为方法的返回值:

        如果主方法调用的方法,该方法的返回值是一个接口,那么可以:

                1可以直接返回:接口的实现类

                2可以直接返回:接口的匿名内部类

                3如果返回值是函数式接口,则可以使用lambda表达式

案例3 使用自定义比较器对字符组进行比较

package com.bed.hanshushijiekou;

import java.util.Arrays;
import java.util.Comparator;

public class ComparatorReturn {
    //因为要改造Comparator,所以方法的返回值是新的Comparator比较器接口
    //方法就叫作getComparator
    public static Comparator<String> getComparator(){
        //111返回值是匿名内部类new Comparator(老方法)
      /*  return new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //按照字符串长度降序排序
                return o2.length()-o1.length();
            }
        };
        //222新方法:因为Comparator接口是一个函数式接口,所以使用lambda表达式
        return (String o1, String o2)->{return o2.length()-o1.length();};
        //333lambda表达式简化*/
        return (o1, o2)->o2.length()-o1.length();//对数组长度进行排序
    }

    public static void main(String[] args) {
        String[] arr={"aaa","bbbbb","c","dd"};
        Arrays.sort(arr,getComparator());//用我们自己定义的方法对arr进行排序
        System.out.println(Arrays.toString(arr));
    }
}

第二部分:常用的函数式接口:

        1、Supprlier接口:生产型接口,泛型参数传递什么类型,返回值就是什么类型

        

package com.bed.hanshushijiekou;

import java.util.function.Supplier;

public class getSupplier {
    //定义一个方法,参数是Supplier接口
    public static String getString(Supplier<String> sup){
        return sup.get();//调用Supplier接口中的get方法,此处返回值也是String类型的
    }

    public static void main(String[] args) {
       // 参数是接口,直接使用lambda表达式,重写Supplier中的get方法,使其返回值满足上面方法(String类型)

        String s = getString(() -> "bed");
        System.out.println(s);
    }
}

           案例:使用Supplier函数式接口获取数组的最大值:

                (其实上面的方法就是一个大的演示框架,而下面的主方法就相当于往构建好的大框架

                        (接口的实现类、lambda表达式)中添加更细致的操作步骤而已)

package com.bed.hanshushijiekou;

import java.util.function.Supplier;

public class SupplierGetMax {
    public static int getmax(Supplier<Integer> sup){
        return sup.get();
    }

    public static void main(String[] args) {
        int[] arr={1,677,66,1,5,56,-23};
        int mmax=getmax(()->{
            int max=arr[0];
            for (int i : arr) {
                if(i>max){
                    max=i;
                }
            }
            return max;//这个就是sup.get方法的返回值
        });
        System.out.println(mmax);
    }
}

                2、Consumer接口(消费者,使用者):

        ​​​​​​​        ​​​​​​​        

         案例,1Consumer的get方法:使用Consumer来逆转名字

package com.bed.hanshushijiekou.ConsumerPratice;

import java.util.function.Consumer;

public class ConsumerPractice {
    public static void getReverse(String name, Consumer<String> con){
        con.accept(name);
    }

    public static void main(String[] args) {
        getReverse("baierdong",(String name)->{
            String rename=new StringBuffer(name).reverse().toString();
            System.out.println(rename);
        });
    }
}

          案例2Consumer的andthen方法:(接力棒操作)

                使用Consumer给字符先变成大写,然后改成小写

package com.bed.hanshushijiekou.ConsumerPratice;

import java.util.function.Consumer;

public class ConsumerAndThen {
    public static void upAndLow(String s, Consumer<String> con1,Consumer<String> con2){
        //先用con1调用accept方法,再使用con2调用accept方法
        con1.andThen(con2).accept(s);
    }

    public static void main(String[] args) {
        upAndLow("xiaobaitu",
           (s)->{//con1的accept方法
               System.out.println(s.toUpperCase());
        }, (s)->{//con2的accept方法
               System.out.println(s.toLowerCase());
                });
    }
}

  案例3、Consumer的andthen方法:

        ​​​​​​​        ​​​​​​​        

        案例重点:1分两次切割,一次是分开数组,一次是按逗号分开        

                          2注意按逗号拆分后,会变成数组状态,前面的元素顺序为【0】第二位元素

                            顺序为【1】......往后以此类推。详情见代码。

package com.bed.hanshushijiekou.ConsumerPratice;

import java.util.function.Consumer;

public class FenZuXianShi {
    //先用此方法拆分数组,拆成一个个的字符串
    public static void chaiFen(String[] main, Consumer<String> con1,Consumer<String> con2){
        for (String s : main) {
            con1.andThen(con2).accept(s);//在该步骤对拆分好的单个数组s进行操作
        }
    }

    public static void main(String[] args) {
        String[] nameage={"bed1,19","bed2,29","bed3,39"};
        chaiFen(nameage,
            (part)->{
            //用[]来把name和age组成为一对;
            String name=part.split(",")[0];//按逗号分开后,拿出[0]号位置元素,也就是name
            System.out.print("姓名"+name+",");
                },
            (part)->{
            String age=part.split(",")[1]; //按逗号分开后,拿出[1]号位置元素,也就是age
            System.out.println("年龄"+age+"。");
                });
    }
}

      2、predicate接口(判断接口):

        ​​​​​​​        ​​​​​​​        ​​​​​​​        

         1.predicate的第一种方法:and(&&)

        ​​​​​​​        ​​​​​​​        ​​​​​​​        

package com.bed.hanshushijiekou.predicate;

import java.util.function.Predicate;

public class CompareNum {
    public static boolean compare(String s, Predicate<String> pre1,Predicate<String> pre2){
        //pre1条件和pre2条件是否同时符合
        return pre1.and(pre2).test(s);//该语句等于pre1.test(s)&&pre2.test(s)
    }

    public static void main(String[] args) {
        String s="abcdef";
        boolean b=compare(s,
                (s1)->{
                    return s.contains("a");
                },
                (s1)->{
                    return s.length()>5;
                });
        System.out.println(b);
    }
}

            2.predicate的第二种方法:or( | | )

        

           3.predicate的第三种方法:negate( !)

        ​​​​​​​        ​​​​​​​        

 案例1 人员筛选:

//筛选器,筛除大于35岁的女性
package com.bed.hanshushijiekou.predicate;

import java.util.ArrayList;
import java.util.function.Predicate;

public class PersonFilter {
    public static ArrayList<String> filter(String[] s, Predicate<String> pre1,Predicate<String> pre2){
        //创建一个数组用来接收结果
        ArrayList<String> fire=new ArrayList<>();
        for (String person : s) {//将数组中的每一组数据拿出来筛选
            if(pre1.and(pre2).test(person)){//如果两个条件同时满足
                fire.add(person);
            }
        }
        return fire;
    }

    public static void main(String[] args) {
        String[] person={"男,35","女,25","男,25","女,40"};
        ArrayList<String> fire=filter(person,
                (String p)->{
                    //按逗号进行分割,判断性别是否为男
                    String sex = p.split(",")[0];
                    return sex.equals("女");
                },
                (String p)->{
                    //按逗号进行分割,判断年龄是否大于35岁
                    String s = p.split(",")[1];
                    Integer i=new Integer(s);//对分隔的字符串进行强制转换
                    return i>=35;
                });
        for (String s : fire) {
            System.out.println(s);
        }
    }
}

3.Function接口:转换接口,吃的是草产的是奶

                1、Function接口中的apply方法

        ​​​​​​​        

package com.bed.hanshushijiekou.Function;

import java.util.function.Function;

public class Function1 {
    public static void getInt(String str, Function<String,Integer> fun){
        Integer apply = fun.apply(str);
        System.out.println(apply);
    }

    public static void main(String[] args) {
        String str="12345";
        getInt(str,(String s)->{
            return Integer.parseInt(s);
        });
    }
}

         1、Function接口中的andthen方法:用来进行组合操作(或是理解为接力棒操作)

        ​​​​​​​        ​​​​​​​        ​​​​​​​        

package com.bed.hanshushijiekou.Function;

import java.util.function.Function;

//实现 1:先将字符串拆分(String to String)
// 2:将字符串转变为Integer类型 (String to Integer)
// 3:转变后再+10(Integer to Integer)
public class FunctionAndthen {
    public static int getInt(String str, //三次转换为用三个FUNCTION接口
                             Function<String,String> fun1,
                             Function<String,Integer> fun2,
                             Function<Integer,Integer> fun3){
       return fun1.andThen(fun2).andThen(fun3).apply(str);
    }

    public static void main(String[] args) {
        String str="bed,9";
        int age=getInt(str,
                (s)->{
                   return s.split(",")[1];//得到的结果还是String类型
                },
                (stoi)->{//从上一个Function进行接力棒操作
                    return Integer.parseInt(stoi);//由String得到Integer
                },
                (i)->{
                    return i+20;//接力棒操作
                });
        System.out.println(age);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值