java8——Lamdba介绍

8 篇文章 0 订阅

Lamdba介绍

Lambda表达式可以理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但是它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。

  • 匿名——我们说匿名,是因为它不像普通的方法那样有一个明确的名称:写得少儿想得多!
  • 函数——我们说它是函数,是因为Lamdba函数不像方法那样属于某个特定的类。但和方法一样,Lamdba有参数列表、函数主体、返回类型,还可能有可以抛出的异常列表。
  • 传递|——Lamdba表达式可以作为参数传递飞方法或存储在变量中。
  • 简介——无需像匿名类那样写很多模板代码。

Lamdba表达式有参数、箭头和主体组成

上图对比一下代码的确简洁了很多

Comparator<Apple> byWeight = new Comparator<Apple>() {
    public int compare(Apple a1, Apple a2){
return a1.getWeight().compareTo(a2.getWeight());
};

词法作用域

在内部类中使用变量名(以及 this)非常容易出错。内部类中通过继承得到的成员(包括来自 Object 的方法)可能会把外部类的成员掩盖(shadow),此外未限定(unqualified)的 this 引用会指向内部类自己而非外部类。

相对于内部类,lambda 表达式的语义就十分简单:它不会从超类(supertype)中继承任何变量名,也不会引入一个新的作用域。lambda 表达式基于词法作用域,也就是说 lambda 表达式函数体里面的变量和它外部环境的变量具有相同的语义(也包括 lambda 表达式的形式参数)。此外,’this’ 关键字及其引用在 lambda 表达式内部和外部也拥有相同的语义。

变量捕获

在 Java SE 7 中,编译器对内部类中引用的外部变量(即捕获的变量)要求非常严格:如果捕获的变量没有被声明为 final 就会产生一个编译错误。我们现在放宽了这个限制——对于 lambda 表达式和内部类,我们允许在其中捕获那些符合 有效只读(Effectively final)的局部变量。

简单的说,如果一个局部变量在初始化后从未被修改过,那么它就符合有效只读的要求,换句话说,加上 final 后也不会导致编译错误的局部变量就是有效只读变量。

Lamdba的基本语法:

(parameters) -> expression 或 (parameters) -> {statements;} 如果主体中是表达式则不需要大括号,而如果是语句则需要大括号。

双冒号语法糖 ::

::为Lamdba的一种语法糖,能够更为简单的实现代码行为化传递,方法应用的例子:

  • 静态方法引用: ClassName::methodName
  • 实例上的实例方法引用:instanceReference::methodName
  • 超类上的实例方法引用:super::methodName
  • 类型上的实例方法引用:ClassName::methodName
  • 构造方法引用:Class::new
  • 数组构造方法引用:TypeName[]::new

简单例子:

// 1. 不需要参数,返回值为 5  
() -> 5  

// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  

// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  

// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  

// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

在List.forEach方法中使用Lamdba:

String[] atp = {"Rafael Nadal", "Novak Djokovic",  
       "Stanislas Wawrinka",  
       "David Ferrer","Roger Federer",  
       "Andy Murray","Tomas Berdych",  
       "Juan Martin Del Potro"};  
List<String> players =  Arrays.asList(atp);  

// 以前的循环方式  
for (String player : players) {  
     System.out.print(player + "; ");  
}  

// 使用 lambda 表达式以及函数操作(functional operation)  
players.forEach((player) -> System.out.print(player + "; "));  

// 在 Java 8 中使用双冒号操作符(double colon operator)  
players.forEach(System.out::println);

在图形界面中使用lamdba来代替内部类:

// 使用匿名内部类  
btn.setOnAction(new EventHandler<ActionEvent>() {  
          @Override  
          public void handle(ActionEvent event) {  
              System.out.println("Hello World!");   
          }  
    });  

// 或者使用 lambda expression  
btn.setOnAction(event -> System.out.println("Hello World!")); 

在Runnable接口中使用Lamdba表达式:

// 1.1使用匿名内部类  
new Thread(new Runnable() {  
    @Override  
    public void run() {  
        System.out.println("Hello world !");  
    }  
}).start();  

// 1.2使用 lambda expression  
new Thread(() -> System.out.println("Hello world !")).start(); 

在Arrays.sort方法中使用Lamdba:

String[] players = {"Rafael Nadal", "Novak Djokovic",   
    "Stanislas Wawrinka", "David Ferrer",  
    "Roger Federer", "Andy Murray",  
    "Tomas Berdych", "Juan Martin Del Potro",  
    "Richard Gasquet", "John Isner"};  

// 1.1 使用匿名内部类根据 name 排序 players  
Arrays.sort(players, new Comparator<String>() {  
    @Override  
    public int compare(String s1, String s2) {  
        return (s1.compareTo(s2));  
    }  
}); 
// 1.2 使用 lambda expression 排序 players  
Comparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2));  
Arrays.sort(players, sortByName);  

// 1.3 也可以采用如下形式:  
Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2))); 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值