其他網址
Java中Lambda表達式的使用 - Franson - 博客園
簡介
Lambda表達式的本質只是一個"語法糖",由編譯器推斷並幫你轉換包裝爲常規的代碼,因此你可以使用更少的代碼來實現同樣的功能。本人建議不要亂用,因爲這就和某些很高級的黑客寫的代碼一樣,簡潔,難懂,難以調試,維護人員想罵娘.)
Lambda表達式是Java SE 8中一個重要的新特性。lambda表達式允許你通過表達式來代替功能接口。 lambda表達式就和方法一樣,它提供了一個正常的參數列表和一個使用這些參數的主體(body,可以是一個表達式或一個代碼塊)。
Lambda表達式還增強了集合庫。 Java SE 8添加了2個對集合數據進行批量操作的包: java.util.function 包以及java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了許多額外的功能。 總的來說,lambda表達式和 stream 是自Java語言添加泛型(Generics)和註解(annotation)以來最大的變化。
Lambda表達式的語法
(parameters) -> expression 或(parameters) ->{ statements; }
lambda表達式的重要特徵
- 可選類型聲明:不需要聲明參數類型,編譯器可以統一識別參數值。
- 可選的參數圓括號:一個參數無需定義圓括號,但多個參數需要定義圓括號。
- 可選的大括號:若主體包含了一個語句,就不需要使用大括號。例: () -> Sysout.out.println("Test");
- 可選的返回關鍵字:若主體只有一個表達式返回值則編譯器會自動返回值,大括號需指定明表達式返回了一個數值。
Lambda 表達式的簡單例子
// 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)
語法格式
左側:Lambda 表達式的參數列表
右側:Lambda 表達式中所需要執行的功能 (Lambda體)語法格式一:無參數,無返回值
() -> Sysout.out.println("Test");語法格式二:有一個參數,並且無返回值
(X)-> Sysout.out.println(x);語法格式三:如果有一個參數括號可以不寫
X-> Sysout.out.println(x);
語法格式四:有兩個以上的參數,有返回值,並且Lambda體中有多條語句 語法體中需要用{}
Comparator<Integer> comparator = (o1, o2) -> {
System.out.println("Test");
return Integer.compare(o1, o2);
};
語法格式五:Lambda體中只用一條語句,return和{}可以省略不寫
Comparator<Integer> comparator = (o1, o2)->Integer.compare(o1, o2);
語法格式六:表達式的參數列表的數據類型可以省略不寫,JVM編譯器通過上下文推斷出數據類型
(x ,y ) ->Integer.compare(x ,y)
變量和作用域
1.Lambda 表達式只能引用標記了 final 的外層局部變量。即不能在 lambda 內部修改定義在域外的局部變量,否則編譯報錯
2.Lambda 表達式的局部變量可以不用聲明爲 final,但是必須不可被後面的代碼修改(即隱性的具有 final 的語義)
3.Lambda 表達式中不允許聲明一個與局部變量同名的參數或者局部變量。
對接口的要求
雖然使用 Lambda 表達式可以對某些接口進行簡單的實現,但並不是所有的接口都可以使用 Lambda 表達式來實現。Lambda 規定接口中只能有一個需要被實現的方法,不是規定接口中只能有一個方法
jdk 8 中有另一個新特性:default, 被 default 修飾的方法會有默認實現,不是必須被實現的方法,所以不影響 Lambda 表達式的使用。
@FunctionalInterface:用來修飾函數式接口,要求接口中的抽象方法只有一個。 此註解往往和 lambda 表達式一起出現。
實例
其他網址
Java8學習筆記(一)--Lambda表達式 - 舒山 - 博客園
Java中Lambda表達式的使用 - Franson - 博客園
函數式接口(無參數無返回值)
package org.example.a;
@FunctionalInterface
interface Interface {
void run();
}
public class Demo{
public static void main(String[] args) {
Interface params = new Interface() {
@Override
public void run() {
System.out.println("Anonymous Internal Class: ");
}
};
Interface params1 = () -> System.out.println("Lambda: ");
params.run();
params1.run();
}
}
執行結果
Anonymous Internal Class:
Lambda:
函數式接口(有參數無返回值)
package org.example.a;
@FunctionalInterface
interface Interface {
void run(String s);
}
public class Demo{
public static void main(String[] args) {
Interface params = new Interface() {
@Override
public void run(String s) {
System.out.println("Anonymous Internal Class: " + s);
}
};
Interface params1 = (s) -> System.out.println("Lambda: " + s);
params.run("hello");
params1.run("hi");
}
}
執行結果
Anonymous Internal Class: hello
Lambda: hi
函數式接口(有參數有返回值)
package org.example.a;
@FunctionalInterface
interface Interface {
String run(String s);
}
public class Demo{
public static void main(String[] args) {
Interface params = new Interface() {
@Override
public String run(String s) {
System.out.println("Anonymous Internal Class: " + s);
return "abc";
}
};
Interface params1 = (s) -> {
System.out.println("Lambda: " + s);
return "def";
};
System.out.println(params.run("hello"));
System.out.println(params1.run("hi"));
}
}
執行結果
Anonymous Internal Class: hello
abc
Lambda: hi
def
遍歷集合
package org.example.a;
import java.util.ArrayList;
import java.util.List;
public class Demo{
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
//以前的循環方式
for (String string : list) {
System.out.println(string);
}
//使用lambda表達式輸出list中的每個值
list.forEach(c->{
System.out.println(c);
});
// 在 Java 8 中使用雙冒號操作符(double colon operator)。也屬於lamda表達式
list.forEach(System.out::println);
}
}
執行結果
aaa
bbb
aaa
bbb
aaa
bbb
創建線程
package org.example.a;
public class Demo{
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Anonymous Internal Class !");
}
}).start();
new Thread(() -> System.out.println("Lambda !")).start();
}
}
執行結果
Anonymous Internal Class !
Lambda !
排序
package org.example.a;
import java.util.Arrays;
import java.util.Comparator;
public class Demo{
public static void main(String[] args) {
String[] players = {"Rafael Nadal", "Novak Djokovic", "Stanislas Wawrinka"};
Arrays.sort(players, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return (o1.compareTo(o2));
}
});
// Comparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2));
// Arrays.sort(players, sortByName);
// Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));
for(String string:players){
System.out.println(string);
}
}
}
執行結果(換成註釋掉的兩種任意一種都是一樣的)
Novak Djokovic
Rafael Nadal
Stanislas Wawrinka