java8新特性:lambda表达式

1、lambda表达式简介

     Java 8的最大变化是引入了Lambda(Lambda 是希腊字母 λ 的英文名称)表达式——一种紧凑的、传递行为的方式。

 lambda写的好可以极大的减少代码冗余,同时可读性也好过冗长的内部类,匿名类。

  • 创建线程

  • 排序

2、lambda表达式语法

2.1、lambda表达式的一般语法

(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
  statment1;
  statment2;
  //.............
  return statmentM;
}

这是lambda表达式的完全式语法后面几种语法是对它的简化

2.2、单参数语法

param1 -> {
  statment1;
  statment2;
  //.............
  return statmentM;
}

当lambda表达式的参数个数只有一个,可以省略小括号

例如:将列表中的字符串转换为全小写

List proNames = Arrays.asList(new String[]{"Ni","Hao","Lambda"});
List lowercaseNames1 = proNames.stream().map(name -> {return name.toLowerCase();}).collect(Collectors.toList());

2.3、单语句写法

param1 -> statment

当lambda表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号

例如:将列表中的字符串转换为全小写

List proNames = Arrays.asList(new String[]{"Ni","Hao","Lambda"});

List lowercaseNames2 = proNames.stream().map(name -> name.toLowerCase()).collect(Collectors.toList());

3、lambda表达式可使用的变量

先举例:

//将为列表中的字符串添加前缀字符串
String waibu = "lambda :";
List proStrs = Arrays.asList(new String[]{"Ni","Hao","Lambda"});
ListexecStrs = proStrs.stream().map(chuandi -> {
Long zidingyi = System.currentTimeMillis();
return waibu + chuandi + " -----:" + zidingyi;
}).collect(Collectors.toList());
execStrs.forEach(System.out::println);

输出:

lambda :Ni -----:1474622341604
lambda :Hao -----:1474622341604
lambda :Lambda -----:1474622341604

 

变量waibu :外部变量

变量chuandi :传递变量

变量zidingyi :内部自定义变量

 

lambda表达式可以访问给它传递的变量,访问自己内部定义的变量,同时也能访问它外部的变量

不过lambda表达式访问外部变量有一个非常重要的限制:变量不可变(只是引用不可变,而不是真正的不可变)。

当在表达式内部修改waibu = waibu + " ";时,IDE就会提示你:

Local variable waibu defined in an enclosing scope must be final or effectively final

编译时会报错。因为变量waibu被lambda表达式引用,所以编译器会隐式的把其当成final来处理

以前Java的匿名内部类在访问外部变量的时候,外部变量必须用final修饰。现在java8对这个限制做了优化,可以不用显示使用final修饰,但是编译器隐式当成final来处理。

4、lambda表达式中的this概念

在lambda中,this不是指向lambda表达式产生的那个SAM对象,而是声明它的外部对象。

例如:

public class WhatThis {

     public void whatThis(){
           //转全小写
           List proStrs = Arrays.asList(new String[]{"Ni","Hao","Lambda"});
           List execStrs = proStrs.stream().map(str -> {
                 System.out.println(this.getClass().getName());
                 return str.toLowerCase();
           }).collect(Collectors.toList());
           execStrs.forEach(System.out::println);
     }

     public static void main(String[] args) {
           WhatThis wt = new WhatThis();
           wt.whatThis();
     }
}

输出:

com.wzg.test.WhatThis
com.wzg.test.WhatThis
com.wzg.test.WhatThis
ni
hao
lambda

5、方法引用

方法引用通过方法的名字来指向一个方法

方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

方法引用使用一对冒号  ::  

下面,我们在 Car 类中定义了 4 个方法作为例子来区分 Java 中 4 种不同方法的引用。

package com.runoob.main;

@FunctionalInterface

public interface Supplier {

      T get();

}

class Car {

          /Supplier是jdk1.8的接口,这里和lamda一起使用了

          public static Car create(final Supplier supplier) {

                  return supplier.get();

         }

         public static void collide(final Car car) {

                   System.out.println("Collided " + car.toString());

         }

       public void follow(final Car another) {

                  System.out.println("Following the " + another.toString());

       }

        public void repair() {

                    System.out.println("Repaired " + this.toString());

          }

}

  • 5.1、构造器引用:

  • 它的语法是Class::new,或者更一般的Class< T >::new实例如下:

  • final Car car = Car.create( Car::new ); final List< Car > cars = Arrays.asList( car );

  • 5.2、静态方法引用:

  • 它的语法是Class::static_method,实例如下:

    cars.forEach( Car::collide );

  • 5.3、特定类的任意对象的方法引用:

  • 它的语法是Class::method实例如下:

    cars.forEach( Car::repair );

  • 5.4、特定对象的方法引用:

  • 它的语法是instance::method实例如下:

    final Car police = Car.create( Car::new );

  • cars.forEach( police::follow );


5.5、方法引用实例

在 Java8Tester.java 文件输入以下代码:

Java8Tester.java 文件

import java.util.List; import java.util.ArrayList;

public class Java8Tester {

           public static void main(String args[]){

                  List names = new ArrayList();

                  names.add("Google");

                  names.add("Runoob");

                  names.add("Taobao");

                  names.add("Baidu");

                  names.add("Sina");

                  names.forEach(System.out::println);

          }

}

实例中我们将 System.out::println 方法作为静态方法来引用。

执行以上脚本,输出结果为:

$ javac Java8Tester.java 
$ java Java8Tester
Google
Runoob
Taobao
Baidu
Sina

你可能感兴趣的:(Java基础)