浅析java lambda表达式及函数式接口@FunctionalInterface

1.Lambda表达式

       Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用 Lambda 表达式可以使代码变的更加简洁紧凑。

lambda表达式语法格式:

(参数列表)->{重写方法体}
//格式一
(parameters) -> expression 
//格式二 
(parameters) ->{ statements; }

lambda表达式用法:

    实现接口重写抽象方法,当接口中只有一个抽象方法时才能使用该表达式。

举例如下:

定义计算器接口,完成接口方法的调用
public class Demo  {
    public static void main(String[] args) {
        //1.调用接口中的实体方法cj(int x,int y)(静态方法)
        //通过接口名.静态方法 完成调用
        System.out.println(Calc.cj(1,5));
        //2.调用接口里的实体方法(默认方法)
        //匿名内部类的对象调用接口里的实体方法
        System.out.println(new Calc() {
            @Override
            public int max(int x, int y) {
                return 0;
            }
        }.sum(2,3));
        //3.jdk 1.8支持 lambda表达式--实现接口重写抽象方法,接口中只有一个抽象方法才能
        使用该表达式
        //语法格式:(参数列表)->{重写方法体}
        Calc c = (int x,int y)->{return x>y?x:y;};
        System.out.println("c"+c.max(1,2));
        //可以省略参数类型不写,重写参数列表被保证
        Calc c1 = (x,y)->{return x>y?x:y;};
        System.out.println("c1"+c1.max(1,2));
        //当重写的方法体只有一句话时,可以省略return以及大括号
        Calc c2 = (x,y)->x>y?x:y;
        System.out.println("c2"+c2.max(1,2));
    }

}

interface Calc{
    //求2个数的最大值
    //抽象方法
    int max(int x,int y);
    //求和--实体化方法
    //1.8 后default 只能在接口中修饰实体方法(默认方法)
    //其他地方无法使用,修饰符 不写就是默认,但是不能加 default
    public default int sum(int x,int y){
        return x+y;
    }
    //求乘积--实体方法(静态方法)--使用更接近抽象类
    public static int cj(int x,int y){
        return x*y;
    }
}

运行结果:

 2.函数式接口

函数式接口在java中是指:有且仅有一个抽象方法的接口,它是java1.8的新特性,函数式接口上添加注解@FunctionalInterface。

函数式接口,即适用于函数式编程场景的接口。而java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。

注:“语法糖"是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部类的“语法糖”,但是二者在原理上是不同的。

函数式接口@FunctionalInterface 的特点:

  • 该注解只能标记在"有且仅有一个抽象方法"的接口上。
  • JDK8接口中的静态方法和默认方法,都不算是抽象方法。
  • 接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。
  • 该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。
     

接口源码:

 注意:Java8新引入函数式编程,函数式编程不属于面向对象。函数式接口,它指的是有且只有一个未实现的方法的接口,一般通过FunctionalInterface这个注解来表明某个接口是一个函数式接口。函数式接口是Java支持函数式编程的基础。

 

对于上面计算器Calc的例子,Calc就是一个函数式接口,加上@FunctionalInterface注解,不会出现错误,运行正常

public class Demo  {
    public static void main(String[] args) {
        //1.调用接口中的实体方法cj(int x,int y)(静态方法)
        //通过接口名.静态方法 完成调用
        System.out.println(Calc.cj(1,5));
        //2.调用接口里的实体方法(默认方法)
        //匿名内部类的对象调用接口里的实体方法
        System.out.println(new Calc() {
            @Override
            public int max(int x, int y) {
                return 0;
            }
        }.sum(2,3));
        //3.jdk 1.8支持 lambda表达式--实现接口重写抽象方法,接口中只有一个抽象方法才能使用该表达式
        //语法格式:(参数列表)->{重写方法体}
        Calc c = (int x,int y)->{return x>y?x:y;};
        System.out.println("c:"+c.max(1,2));
        //可以省略参数类型不写,重写参数列表被保证
        Calc c1 = (x,y)->{return x>y?x:y;};
        System.out.println("c1:"+c1.max(1,2));
        //当重写的方法体只有一句话时,可以省略return以及大括号
        Calc c2 = (x,y)->x>y?x:y;
        System.out.println("c2:"+c2.max(1,2));
    }

}
//定义计算器接口
//函数式接口--@FunctionalInterface--直接使用lambda表达式
//函数式编程--不属于面向对象
@FunctionalInterface
interface Calc{
    //求2个数的最大值
    //抽象方法
    int max(int x,int y);
    //求和--实体化方法
    //1.8 后default 只能在接口中修饰实体方法(默认方法)
    //其他地方无法使用,修饰符 不写就是默认,但是不能加 default
    public default int sum(int x,int y){
        return x+y;
    }
    //求乘积--实体方法(静态方法)--使用更接近抽象类
    public static int cj(int x,int y){
        return x*y;
    }
}

运行结果:

3.函数式接口和Lambda表达式的用法举例

示例一:

public class LambdaDemo {
    public static void main(String[] args) {
        int[] arr = {1,8,7,5};
        //Lambda 表达式  arr1 不能与上面的arr 重名
        //Arraysort a = (int[] arr1)-> Arrays.sort(arr1);
        //写法二
        //参数类型和重写方法体的大括号可以省略
        //Arraysort a = (arr1)->Arrays.sort(arr1);
        //当参数只有一个时小括号可以省略
        //Arraysort a = arr1->Arrays.sort(arr1);
        // :: 代表传递静态方法
        Arraysort a = Arrays::sort;
        //给数组排序
        a.sortArray(arr);
        //测试
        System.out.println(Arrays.toString(arr));
    }

}

//函数式接口
interface Arraysort{
    //给数组排序
    void sortArray(int[] arr);
}

示例二:

 

public class LambdaDemo2 {
    public static void main(String[] args) {
        //
        List<String> list = new ArrayList<>();
        //添加元素
        list.add("b");
        list.add("a");
        list.add("c");
        list.add("d");
        list.add("e");
        //Comparator --比较器
        //Comparator 是函数式接口--@FunctionalInterface--直接使用lambda表达式
   /*     list.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.charAt(0)-o2.charAt(0);
            }
        });*/
        list.sort(((o1, o2) -> o1.charAt(0)-o2.charAt(0)));
        //输出结果
        System.out.println(list);
    }
}

示例三:

public class LambdaDemo3 {
    public static void main(String[] args) {

        //创建代表文件类的对象
        File file = new File("D:\\filetest");

        //过滤获取的所有信息名称中是否含有数字
/*       File[] fs = file.listFiles(new FileFilter() {
            //指定过滤规则
            @Override
            public boolean accept(File pathname) {
                //数量词--表示前面可以出现次数
                //.代表任意字符
                //正则语法匹配是否含有数字
                return pathname.getName()
                        .matches(".*\\d.*");
            }
        });*/
        //使用lambda 表达式
      /*  File[] fs = file.listFiles(pathname->pathname.getName()
                .matches(".*\\d.*"));*/

    /*    File[] fs = file.listFiles(new FilenameFilter() {
            //指定过滤规则
            @Override
            public boolean accept(File dir, String name) {
                return name.matches(".*\\d.*");
            }
        });*/
        //使用lambda 表达式
        File[] fs = file.listFiles(((dir, name) -> name.matches(".*\\d.*")));

        for (File f:fs
             ) {
            System.out.println(f);
        }
    }
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值