【Java】Lambda入門
阿新 • • 發佈:2021-02-10
本文是Lambda的入門文章。主要向讀者介紹Lambda的基本概念和寫法。主要面向的讀者是Java新手。
主要內容:
- Lambda到底是什麼東西?
- 怎麼通過Lambda簡化程式碼?
背景知識:其中在逐步推導Lambda表示式時,需要用到併發程式設計中的Runnable介面。
目錄
什麼是Lambda
基本特性:
- 是JDK1.8開始之後的新技術,是一種程式碼的新語法。
- 目的是為了簡化匿名內部類
使用前提:
- 首先必須是介面。
- 介面中只能有一個抽象方法。
- 即,Lambda表示式只能簡化介面中只有一個抽象方法的匿名內部類形式。
函式式介面:
- 介面中只有一個抽象方法的介面稱為函式式介面。
- 函式式介面註解:@FunctionalInterface 一旦某個介面加上了這個註解,這個介面只能、有且僅有一個抽象方法。
Lambda 語法
- (params) -> expression
- (params) -> statement
- (params) -> { statements }
- 左側: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) -> { 方法體(如果方法體可以使用一句程式碼,則可以省略花括號) }