1. 程式人生 > 其它 >【Java】Lambda入門

【Java】Lambda入門

技術標籤:# JavaSEJavaLambda

本文是Lambda的入門文章。主要向讀者介紹Lambda的基本概念和寫法。主要面向的讀者是Java新手。

主要內容:

  • Lambda到底是什麼東西?
  • 怎麼通過Lambda簡化程式碼?

背景知識:其中在逐步推導Lambda表示式時,需要用到併發程式設計中的Runnable介面。


目錄

什麼是Lambda

第一個Lambda表示式

原始寫法

靜態內部類簡化

區域性內部類簡化

匿名內部類簡化

Lambda簡化

再簡化

Lambda例項


什麼是Lambda

基本特性:

  1. 是JDK1.8開始之後的新技術,是一種程式碼的新語法。
  2. 目的是為了簡化匿名內部類
    的程式碼寫法

使用前提:

  1. 首先必須是介面
  2. 介面中只能有一個抽象方法。
  3. 即,Lambda表示式只能簡化介面中只有一個抽象方法的匿名內部類形式。

函式式介面:

  1. 介面中只有一個抽象方法的介面稱為函式式介面
  2. 函式式介面註解:@FunctionalInterface 一旦某個介面加上了這個註解,這個介面只能、有且僅有一個抽象方法。

Lambda 語法

  1. (params) -> expression
  2. (params) -> statement
  3. (params) -> { statements }
  4. 左側:Lambda 表示式的引數列表;右側:Lambda 表示式中所需執行的功能, 即 Lambda 體

第一個Lambda表示式

在併發程式設計中,我們可以通過實現Runnable介面來開闢一個新的任務執行緒。下面,通過任務執行緒的程式碼編寫,來理解Lambda是如何簡化寫法的。

原始寫法

首先明確,Runnable介面只有一個方法,滿足函式式介面的條件:

以下是常規的寫法:

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyThread()); //建立一個執行緒
        thread.start(); //執行執行緒
    }
}

//實現Runnable介面,實現任務執行緒
class MyThread implements Runnable {
    @Override
    public void run() {
        System.out.println("執行緒"+Thread.currentThread().getName()+"執行了!");
    }
}

靜態內部類簡化

將執行緒任務類放在要呼叫內的內部,作為靜態內部類或者成員內部類:

public class Main {
    //實現Runnable介面,實現任務執行緒
    public static class MyThread implements Runnable {
        @Override
        public void run() {
            System.out.println("執行緒"+Thread.currentThread().getName()+"執行了!");
        }
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new MyThread()); //建立一個執行緒
        thread.start(); //執行執行緒
    }
}

區域性內部類簡化

把任務執行緒放在方法體內、區域性變數的位置:

public class Main {
    public static void main(String[] args) {
        class MyThread implements Runnable { //區域性內部類,就相當於申明一個變數
            @Override
            public void run() {
                System.out.println("執行緒"+Thread.currentThread().getName()+"執行了!");
            }
        }

        Thread thread = new Thread(new MyThread()); //建立一個執行緒
        thread.start(); //執行執行緒
    }
}

匿名內部類簡化

省略實現類類名的方式,其中“new Runnable() {}”,等價於“class 名字 implements Runnable() {}”:

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("執行緒"+Thread.currentThread().getName()+"執行了!");
            }
        }); //申明任務執行緒

        thread.start(); //執行執行緒
    }
}

Lambda簡化

Lambda的簡化格式:

(匿名內部類被重寫方法的形參列表) -> {

被重寫方法的方法體程式碼。

}

Lambda簡化:

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

        //使用Lambda簡化:
        // 把"public void run()"簡化為"()"。
        // 之所以不用指定方法名,是因為函式式介面中有且僅有一個方法,只要一呼叫,只有那一個方法可以呼叫
        // 方法體保持不變
        Thread thread = new Thread( () -> {
            System.out.println("執行緒"+Thread.currentThread().getName()+"執行了!");
        });
        thread.start();
    }
}

再簡化

再簡化:
public class Main {
    public static void main(String[] args) {
        //方法體內只有一行程式碼,可以直接去掉方法體的花括號:{}
        Thread thread = new Thread(() -> System.out.println("執行緒"+Thread.currentThread().getName()+"執行了!") );
        thread.start();
    }
}


匿名物件的簡化:
public class Main {
    public static void main(String[] args) {
        //把Thread類轉換為匿名物件
        new Thread(() -> System.out.println("執行緒"+Thread.currentThread().getName()+"執行了!")).start();
    }
}

Lambda例項

Lambda簡化Comparator介面匿名內部類寫法:

public static void main(String[] args) {
    List<Student> lists = new ArrayList<>();
    Student s1 = new Student("李銘",18,'男');
    Student s2 = new Student("馮龍",23,'男');
    Student s3 = new Student("王樂樂",21,'男');
    Collections.addAll(lists , s1 , s2 , s3);

    // 按照年齡進行升序排序!
    Collections.sort(lists, new Comparator<Student>() {
        @Override
        public int compare(Student s1, Student s2) {
            return s1.getAge() - s2.getAge();
        }
    });

    // Lambda簡化寫法
    Collections.sort(lists, (Student t1, Student t2) -> {
        return t1.getAge() - t2.getAge();
    });
    // 如果Lambda表示式的方法體程式碼只有一行程式碼。可以省略大括號不寫。
    // 此時,如果這行程式碼是return語句,必須省略return不寫,同時也必須省略";"不寫
    Collections.sort(lists,(Student t1, Student t2) -> t1.getAge() - t2.getAge());

    // 引數型別可以省略
    Collections.sort(lists, (t1,  t2) -> t1.getAge() - t2.getAge());

    System.out.println(lists);
}

forEach遍歷簡化

public static void main(String[] args) {
    List<String> names = new ArrayList<>();
    names.add("胡偉光");
    names.add("甘挺");
    names.add("洪磊");

    //forEach遍歷原理
    names.forEach(new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    });

    //Lambda簡化
    names.forEach((String s) -> {
        System.out.println(s);
    });

    //省略入參型別
    names.forEach((s) -> {
        System.out.println(s);
    });
    //如果只有一個引數,省略:入參括號
    names.forEach(s -> {
        System.out.println(s);
    });

    //Lambda表示式的方法體程式碼只有一行程式碼,省略花括號、分號
    names.forEach(s -> System.out.println(s) );

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

總結:

  • Lambda的作用是簡化程式碼的寫法,減少程式碼量。
  • 核心語法是:(引數1,引數2) -> { 方法體(如果方法體可以使用一句程式碼,則可以省略花括號) }