java中Lambda表达式


Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。Lambda 表达式(Lambda expression),基于数学中的λ演算得名,也可称为闭包(Closure) 。

Lambda表达式的语法

基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }
Lambda表达式由三部分组成:

  1. paramaters:类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。

  2. ->:可理解为“被用于”的意思

  3. 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回

函数式接口

要了解Lambda表达式,首先需要了解什么是函数式接口,函数式接口定义:一个接口有且只有一个抽象方法 。

注意:

  1. 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口

  2. 如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接
    口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只
    有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的。

@FunctionalInterface
interface NoParameterNoReturn {
 //注意:只能有一个方法
    void test();
    }

但是这种方式也是可以的:

@FunctionalInterface

interface NoParameterNoReturn {
    void test();
    default void test2() {
        System.out.println("JDK1.8新特性,default默认方法可以有具体的实现");
   }
}

Lambda表达式的基本使用

1.无参数无返回值

  //无返回值无参数
@FunctionalInterface
   interface NoParameterNoReturn{
        //注意:函数式接口只能有一个抽象方法
        void test();
        }
        public class lambda {
     public static void main(String[] args) {
        NoParameterNoReturn noParameterNoReturn = () -> System.out.println("hello");
                noParameterNoReturn.test();
    }
    }

在这里插入图片描述
2.无返回值一个参数

 //无返回值一个参数
        @FunctionalInterface
        interface OneParameterNoReturn {
            void test(int a);
        }
          public class lambda {
          public static void main(String[] args) {
 //参数类型只有一个可以省略还可以省略参数的括号
                OneParameterNoReturn oneParameterNoReturn = (x) -> System.out.println(x + 10);
                oneParameterNoReturn.test(19);
            }
            }

在这里插入图片描述

3.无返回值多个参数

    //无返回值多个参数
        @FunctionalInterface
        interface MoreParameterNoReturn {
            void test(int a, double b);
        }
      
          public class lambda {
          public static void main(String[] args) {
 //类型不可以单独省略,除非一起省略
                MoreParameterNoReturn moreParameterNoReturn = (x, y) -> System.out.println(x + y);
                moreParameterNoReturn.test(10, 20);
            }
            }

在这里插入图片描述
4.有返回值无参数

    //有返回值无参数
        @FunctionalInterface
        interface NoParameterReturn {
            int test();
        }
                  public class lambda {
                  public static void main(String[] args) {
 //              //可以省略return
//        NoParameterReturn noParameterReturn=()->{return 10;};
                NoParameterReturn noParameterReturn = () -> 10;
                int ret = noParameterReturn.test();
                System.out.println(ret);
            }
            }

在这里插入图片描述
5.有返回值一个参数

      //有返回值一个参数
        @FunctionalInterface
        interface OneParameterReturn {
            int test(int a);
        }
         public class lambda {
          public static void main(String[] args) {
          OneParameterReturn oneParameterReturn = x -> x + 10;
                int ret = oneParameterReturn.test(9);
                System.out.println(ret);
                }
               }

在这里插入图片描述
6.有返回值多参数

  //有返回值多参数
        @FunctionalInterface
        interface MoreParameterReturn {
            int test(int a, int b);
        }
         public class lambda {
          public static void main(String[] args) {
            MoreParameterReturn moreParameterReturn = (x, y) -> x * y;
                int ret = moreParameterReturn.test(10, 20);
                System.out.println(ret);
            }
           }

在这里插入图片描述

语法精练

  1. 参数类型可以省略,如果需要省略,每个参数的类型都要省略。

  2. 参数的小括号里面只有一个参数,那么小括号可以省略

  3. 如果方法体当中只有一句代码,那么大括号可以省略

  4. 如果方法体中只有一条语句,且是return语句,那么大括号可以省略,且去掉return关键字

变量捕获

Lambda 表达式中存在变量捕获 ,了解了变量捕获之后,我们才能更好的理解Lambda 表达式的作用域 。Java当中的匿名类中,会存在变量捕获

匿名内部类的变量捕获

class Test {
    public void func(){
        System.out.println("func()");
   }
}

public class TestDemo {
    public static void main(String[] args) {
        int a = 100;
        new Test(){
            @Override
            public void func() {
                System.out.println("我是内部类,且重写了func这个方法!");
                System.out.println("我是捕获到变量 a == "+a

                        +" 我是一个常量,或者是一个没有改变过值的变量!");
           }
       };
   }
}

在这里插入图片描述
此时这个代码可以正常运行,而当匿名内部类中修改a的值此时就会报出错误

class Test {
    public void func(){
        System.out.println("func()");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        int a = 100;
        new Test(){
            @Override
            public void func() {
                a=99;
                System.out.println("我是内部类,且重写了func这个方法!");
                System.out.println("我是捕获到变量 a == "+a +" 我是一个常量,或者是一个没有改变过值的变量!");
            }
        };

    }
}

在这里插入图片描述
在上述代码当中的变量a就是,捕获的变量。这个变量要么是被final修饰,如果不是被final修饰的 你要保证在使用之前,没有修改

Lambda的变量捕获

@FunctionalInterface
interface NoParameterNoReturn {
    void test();
}

public static void main(String[] args) {
        int a = 10;
        NoParameterNoReturn noParameterNoReturn = ()->{
            // a = 99; error
            System.out.println("捕获变量:"+a);
       };
        noParameterNoReturn.test();
}

Lambda在集合当中的使用

Collection接口
forEach() 方法演示

 public static void main(String[] args) {
                List<String> list = new ArrayList<>();
                list.add("hello");
                list.add("this");
                list.add("day");
                list.forEach(new Consumer<String>() {
                    @Override
                    public void accept(String s) {
                        System.out.println(s);
                    }
                });
                System.out.println("==========");
                list.forEach(s -> System.out.println(s));
                }

在这里插入图片描述

List接口
sort()方法

public static void main(String[] args) {
                List<String> list = new ArrayList<>();
                list.add("hello");
                list.add("this");
                list.add("day");
 list.sort(new Comparator<String>() {
                    @Override
                    public int compare(String o1, String o2) {
                        return o1.compareTo(o2);
                    }
                });
                list.sort((o1, o2) -> {
                    return o1.compareTo(o2);
                });
                list.forEach(s -> System.out.println(s));
            }

在这里插入图片描述

Map接口
HashMap的forEach()

public static void main(String[] args) {
                Map<String, Integer> hashMap = new HashMap<>();
                hashMap.put("hello", 3);
                hashMap.put("abc", 2);
                hashMap.put("this", 5);
                hashMap.forEach(new BiConsumer<String, Integer>() {
                    @Override
                    public void accept(String s, Integer integer) {
                        System.out.println("key" + s + "vay" + integer);
                    }
                });
                hashMap.forEach((String s, Integer integer) -> System.out.println("key" + s + "vay" + integer));
            }

在这里插入图片描述

Lambda优点和缺点

优点:

  1. 代码简洁,开发迅速

  2. 方便函数式编程

  3. 非常容易进行并行计算

  4. Java 引入 Lambda,改善了集合操作 缺点:

  5. 代码可读性变差

  6. 在非并行计算中,很多计算未必有传统的 for 性能要高

  7. 不容易进行调试

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值