函数式接口总结及代码演示

函数式接口总结及代码演示

1.函数式接口

函数式接口简单定义:有且只有一个抽象方法的接口。
接口中可以包含其他方法:包括默认方法,其他方法,私有方法。

  • 定义一个函数式接口
    可用@FunctionalInterface注解。
    其作用是检测接口是否是一个函数式接口,若是则编译成功,若不是则编译失败。

  • 代码演示

@FunctionalInterface
public interface MyFunctionalInterface {
   //public abstract可以省略,但有时为了代码清晰易懂,最好写上。
   public abstract void method();
}
  • 接口实现类为(对比作用)
public class MyFunctionalInterfaceImpl implements MyFunctionalInterface{
   @Override
   public void method() {
   }
}
  • demo
/*
函数式接口的使用:一般可以作为方法的参数和返回值类型
*/
public class Demo {
   public static void show(MyFunctionalInterface myInter) {
       myInter.method();
   }

   public static void main(String[] args) {
       //传递接口的实现类对象
       show(new MyFunctionalInterfaceImpl());

       //使用接口的匿名内部类
       show(new MyFunctionalInterface() {
           @Override
           public void method() {
               System.out.println("使用匿名内部类重写接口中的抽象方法");
           }
       });

       //调用show方法,方法参数是函数式接口,可以使用Lambda表达式
       show(()-> {
           System.out.println("使用Lambda表达式重写接口中的抽象方法");
       });
   }
}

2.Lambda方式的优越性

  • 写一个日志案例,首先不使用lambada方式,代码如下
/*
日志案例

   发现:以下代码存在性能浪费问题
       过程中先拼接字符串,再调用showLog方法
       若level不等于1,则还是进行了拼接字符串操作,浪费性能
*/
public class Demo1Logger {
   //根据日志的级别显示日志信息的方法
   public static void showLog(int level, String message) {
       //对日志的等级进行判断,如果是1,输出日志类信息
       if(level == 1) {
           System.out.println(message);
       }
   }

   public static void main(String[] args) {
       //定义三个日志信息
       String msg1 = "Hello";
       String msg2 = "World";
       String msg3 = "Java";

       //调用showLog,传递日志级别和日志信息
       showLog(2,msg1+msg2+msg3);
   }
}

代码存在性能浪费问题,即将level=2的话,是不显示字符串信息的,但是字符串也进行了拼接操作。

  • 使用lambda方式
/**
 * 使用Lambda优化日志案例
 * Lambda优点:延迟加载
 * Lambda使用前提:必须存在函数式接口
 */
public class Demo02Lambda {
    //定义显示日志的方法
    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方法,MessageBuilder是一个函数式接口,所以可以使用lambda表达式
        showLog(1,()->{
            //测试
            System.out.println("不满足条件不执行");
            //返回拼接好的字符串
            return msg1+msg2+msg3;
        });

        /**
         * 使用lambda表达式作为参数传递。仅仅是把参数传递到showLog方法中,
         * 只有满足条件:日志的等级是1级, 才会调用接口中的方法,才会进行字符串的拼接
         * 如果条件不满足:接口中的方法不会执行
         */
    }
}

这里若将level=2,是不会打印输出语句的,证明若前面条件不成立,lambda是不会执行的,所以可以总结出lambda是具有延迟加载的优点。

3.函数式接口作为参数类型

public class Demo01Runnable {
	//Runnable接口就是一个函数式接口
    public static void startThread(Runnable run) {
        //启用多线程
        new Thread(run).start();
    }

    public static void main(String[] args) {
        //调用startThread方法,方法的参数是一个接口,那么可以传递这个接口的匿名内部类
        startThread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"-->"+"线程启动了");
            }
        });

        //使用lambda表达式 方法的参数是函数式接口  所以使用lambda表达式
        startThread(()->{
            System.out.println(Thread.currentThread().getName()+"-->"+"线程启动了");
        });
    }
}

4.常用函数式接口

1.supplier接口
/**
 * 常用函数式接口
 * Supplier<T> 接口被称之为生产型接口,指定接口的泛型是什么类型,接口中的get方法就会生产什么类型的数据
 */
public class Demo01Supplier {
    public static String getString(Supplier<String> sup) {
        return sup.get();
    }

    public static void main(String[] args) {
        //调用getString方法,参数是一个函数式接口
         String s = getString(()->{
           //生产一个字符串并返回
           return "james";
        });
         System.out.println(s);
    }
}

应用:返回数组中的最大值

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

    public static void main(String[] args) {
        int[] arr = {11,2,23,4,555,51};
        int x = getMax(()->{
           //获取数组的最大值并返回
           //定义一个变量,把数组中第一个元素赋值给该变量,记录数组中元素的最大值
            int max = arr[0];
            for(int i : arr){
                if(max<i){
                    max = i;
                }
            }
            return max;
        });
        System.out.println(x);
    }
}

02.Consumer接口

Consumer是一个消费型接口,泛型执行什么类型,就可以用accept方法消费什么类型的接口

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

    public static void main(String[] args) {
        /*
        调用method方法,传递name,传递接口
         */
        method("james",(t)->{
            //对传递的字符串进行消费
            //消费方式1 打印
            System.out.println(t);
            //消费方式2 反转
            String rename = new StringBuilder(t).reverse().toString();
            System.out.println(rename);
        });
    }
}

andThen方法
Consumer默认方法 andThen
作用:需要两个Consumer接口,可以结合两个接口组合在一起再对数据进行消费

例如:
Consumer con1
Consumer con2
String s = “hello”
con1.accept(s)
con2.accept(s)
等同于 谁写前面,谁先消费
con1.andThen(con2).accept(s)

public class Demo02Consumer {
   //定义一个方法,参数是一个字符串和两个Consumer接口
   public static void method(String s, Consumer<String> con1,Consumer<String> con2) {
//        con1.accept(s);
//        con2.accept(s);
       //把两个Consumer连接在一起,使用andThen  先执行con1 后con2
       con1.andThen(con2).accept(s);
   }

   public static void main(String[] args) {
       method("James",
               (t)->{
           System.out.println(t.toUpperCase());
       },
               (t)->{
           System.out.println(t.toLowerCase());
       });
   }
}

应用:格式化打印信息

public class Demo03Consumer {

    public static void printInfo(String[] array, Consumer<String> con1,Consumer<String> con2) {
        for(String info : array) {
            con1.andThen(con2).accept(info);
        }
    }

    public static void main(String[] args) {
        String[] array = {"James,23","Kobe,24","Jordan,23"};
        printInfo(array,
                (s)->{
            System.out.print("姓名:"+s.split(",")[0]);
        },
                (s)->{
            System.out.println("。号码"+s.split(",")[1]+".");
                }
        );
    }
}

3.Predicate接口

判断型接口
Predicate 对某种数据类型的数据进行判断 结果返回一个bool值 boolean test(T t)

public class Demo01Predict {

    public static boolean checkString(String s, Predicate<String> pre) {
        return pre.test(s);
    }

    public static void main(String[] args) {
        String s = "abcde";
        boolean b = checkString(s,(t)->{
            return t.length()>5;
        });
        System.out.println(b);
    }
}

应用: 定义一个方法,方法的参数,传递一个字符串 ,传递两个Predicate接口
* 一个用于判断字符串长度是否大于5
* 一个用于判断字符串中是否包含0
* 两个条件必须同时满足

public class Demo02Predict {

    public static boolean checkString(String s, Predicate<String> pre1,Predicate<String> pre2) {
        return pre1.test(s) && pre2.test(s);
    }

    public static void main(String[] args) {
        String s = "512345";
        boolean flag = checkString(s,
                (t)->{
            return t.length()>5;
                },
                (t)->{
            return t.contains("0");
                });
        System.out.println(flag);
    }
}
4.Function接口

根据一个类型的数据转换为另一个类型的数据

public class DemoFunction {
    public static void change(String s, Function<String,Integer> fun) {
        Integer in = fun.apply(s);
        System.out.println(in);
    }

    public static void main(String[] args) {
        String s = "50";
        change(s,(t)->{
            return Integer.parseInt(t);
        });
    }
}

需求:
把String类型转换为Integer 转换后结果+10再转换为String

public class Demo2Function {
    public static void change(String s, Function<String,Integer> fun1,Function<Integer,String> fun2) {
        String str = fun1.andThen(fun2).apply(s);
        System.out.println(str);
    }

    public static void main(String[] args) {
        String s= "1245";
        change(s,
                (t)->{
            return Integer.parseInt(t)+10;
                },
                (t)->{
            return t.toString();
                });
    }
}

需求:

  • 用Function进行函数模型的拼接:
  • String str = “james,23”;
  • 1.将字符串截取数字年龄部分,得到字符串;
  • 2.将上一步的字符串转换为int类型的数据;
  • 3.将上一步的数据累加100,得到int数字
public class Demo3Function {
    public static void change(String str, Function<String,String> fun1,Function<String,Integer> fun2,Function<Integer,Integer> fun3) {
        int age = fun1.andThen(fun2).andThen(fun3).apply(str);
        System.out.println(age);
    }

    public static void main(String[] args) {
        String str = "james,23";
        change(str,
                (String t)->{
            return t.split(",")[1];
                },
                (String t)->{
            return Integer.parseInt(t);
                },
                (Integer t)->{
            return t+100;
                });
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值