Java8---Lambda表达式

了解Lambda表达式之前,需要对匿名内部类与函数式接口了解。

一、函数式接口

1.有且只有一个抽象方法,但可以有多个非抽象方法。

2.可以隐式的转换为 Lambda 表达式。

3.可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时javadoc也会包含一条声明,声明这个接口是一个函数式接口。

在 JDK1.8之前,java就包含了许多函数式接口,

java.lang.Runnable ,java.util.concurrent.Callable ,java.security.PrivilegedAction ,java.awt.event.ActionListener ,
java.io.FileFilter ,java.nio.file.PathMatcher ,java.lang.reflect.InvocationHandler ,java.beans.PropertyChangeListener ,
java.util.Comparator ,javax.swing.event.ChangeListener

java8 新增  java.util.function ,包下包含多个函数式接口,用来支持函数式编程。

/**
 * @author YoonaLt
 * 有参数,无返回值 的函数式接口
 */
@FunctionalInterface
public interface MyFunctionalInterface {

    /**
     * 函数式接口有且仅有一个抽象方法
     * 接口中,成员变量的默认修饰符为 public static final,成员方法的默认修饰符为 public abstract.
     *
     * @param s 参数
     */
    void onlyAbstractMethod(String s);

    /**
     * 可以含有多个其他非抽象方法
     * 这个方法是一个默认方法,使用默认方法的优势是给接口添加新方法的同时不影响已有的实现.在工作中解                
     * 决接口的修改与现有的实现不兼容的问题是非常有效的.
     */
    default void otherFunction() {
        System.out.println("这是函数式接口的非抽象方法,可以有多个");
    }
}

 

二、Lambda表达式

Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把 函数 作为一个方法的 参数(函数作为参数传递进方法中)。

使用Lam不打可以代替匿名内部类,匿名方法的使用,简化代码,减少类文件的生成。但是代码可读性不高,使用场景有限制。

Lambda表达式的写法一般为

(parameters) -> expression 或 (parameters) ->{ statements; }

其重要特性为

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体只包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
//无参,使用空的 () 表示
() -> body

// 一个参数,参数可以用 () 包裹,也可以不用.当 body 主体只包含一个语句时,花括号可以省略不写, param -> body;
(param) -> { body; } 或 param -> { body; } 

// 多个参数
(param1, param2...) -> { body }

参数 param param1 param2 的类型不需要指定(typeOne param1,typeTwo param2),编译器可以从上下文推断参数类型.

1.上面示例 有参数,无返回值 的函数式接口转变为 Lambda 表达式为

MyFunctionalInterface myFunctionalInterface = (s) -> System.out.println(s); 
方法引用的方式
MyFunctionalInterface myFunctionalInterface = System.out::println;

myFunctionalInterface.onlyAbstractMethod("转换为Lambda表达式");

 

2.有参数,有返回值的函数式接口

/**
 * @author YoonaLt
 * 有参数,有返回值的函数式接口
 */
@FunctionalInterface
public interface MyTest<T, E> {
    E myMethod(T t);
}

转变为Lambda表达式为

MyTest<String, Integer> myTest = (s) -> {return Integer.parseInt(s);};
方法引用的方式
MyTest<String, Integer> myTest = = Integer::parseInt;

myTest.myMethod("1");

 

3. Lambda 表达式比较典型的应用就是线程初始化

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("原方式创建一个线程");
            }
        }).start();

使用Lambda表达式后,就可以简化为

new Thread(() -> System.out.println("使用Lambda表达式")).start();

实际工作中并不推荐显示的创建一个线程,强烈建议使用线程池的方式创建线程,这里只是提供一个示例。

 

4.Lambda表达式也可在集合使用 forEach 方法时使用,比如下面这个示例

        List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6);
        List<Integer> result = new ArrayList<>();
        int min = 2;
        list.forEach(i -> {
            if (i > min) {
                result.add(i);
            }
        });
        result.forEach(System.out::println);

需要注意的是,Lambda表达式使用外部局部变量时,外部局部变量修饰符只能为 final(如忽略不写,编译器会默认其为 final 修饰),当你在 Lambda 表达式内部试图修改外部局域变量时,会报错

 

由于本人水平有限,难免有错误和疏漏,请不吝赐教.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章