一文搞懂Java中的lambda匿名函數(shù)
1 Lambda表達式
Lambda函數(shù),也稱為Lambda表達式,是Java 8版本新增的一項功能。它提供了一種簡潔的方式來定義小型匿名函數(shù),這些函數(shù)可以作為參數(shù)傳遞給其他方法或作為返回值使用。
語法:
Lambda表達式可以使用這個語法->來表示。
示例:
零參數(shù):() -> expression
interface PrintInfo {
void print();
}
class TestLambda {
static void printJob(PrintInfo printInfo) {
printInfo.print();
}
public static void main(String[] args) {
printJob(() -> System.out.println("We're learning Java 8 fundamentals !"));
}
}
Output: We’re learning Java 8 fundamentals !
一個參數(shù):parameter -> expression
interface PrintInfo {
void print(String data);
}
class TestLambda {
static void printJob(PrintInfo printInfo, String data) {
printInfo.print(data);
}
public static void main(String[] args) {
printJob(statement -> System.out.println("We're learning " + statement), "Lambda");
}
}
Output: We're learning Lambda
多個參數(shù):(parameter1, parameter2) -> expression
interface PrintInfo {
void print(String data1, String data2);
}
class TestLambda {
static void printJob(PrintInfo printInfo, String data1, String data2) {
printInfo.print(data1, data2);
}
public static void main(String[] args) {
printJob((statement1, statement2) -> System.out.println("We're learning " + statement1 + " and "+ statement2), "Lambda", "it's uses");
}
}
Output: We're learning Lambda and it's uses
復(fù)雜表達式:(parameter1, parameter2) -> { complex code block }
interface PrintInfo {
void print(String data1, String data2);
}
class TestLambda {
static void printJob(PrintInfo printInfo, String data1, String data2) {
printInfo.print(data1, data2);
}
public static void main(String[] args) {
printJob((statement1, statement2) -> {
System.out.println("We're learning " + statement1 + " and "+ statement2);
System.out.println("This is a multi line lambda");
System.out.println("This is a complex lambda implementation");
},
"Lambda",
"it's uses"
);
}
}
Output: We’re learning Lambda and it’s uses
This is a multi line lambda
This is a complex lambda implementation
2 方法引用
方法引用是一種緊湊、易讀的Lambda表達式,用于已經(jīng)具有名稱的方法。簡單地說,我們可以使用方法引用從Lambda函數(shù)中調(diào)用方法。
語法:
Object::method
讓我們來看看如何使用Lambda打印列表中的元素:
public void print(List<String> list) {
list.forEach(l -> System.out.println(l));
}
可以使用方法引用,如下所示:
public void print(List<String> list) {
list.forEach(System.out::println);
}
如您所見,這使代碼更加清晰、精確和易于閱讀。
同樣地,我們可以使用Classname::methodName來表示對靜態(tài)方法的調(diào)用。
public static void main(String[]args){
List<String> fruits = new ArrayList<>();
fruits.add("mango");
fruits.add("banana");
fruits.add("kiwi");
fruits.add("orange");
fruits.forEach(Test::process);
}
private static void process(String value) {
System.out.println("processed fruit: " + value);
}
同時,我們可以使用Object to be instantiated::new來使用方法引用引用構(gòu)造函數(shù)。
public static void main(String[]args){
List<String> fruits = new ArrayList<>();
fruits.add("mango");
fruits.add("banana");
fruits.add("kiwi");
fruits.add("orange");
fruits.stream()
.map(Fruit::new)
.toArray(Fruit[]::new);
}
class Fruit {
public Fruit(String name) {
this.name = name;
}
}
方法引用也可以用于Comparator。
按名稱對水果列表排序:
public static void process(List<Fruit> fruits) {
fruits.stream()
.sorted(Comparator.comparing(Fruit::getName))
.forEach(System.out::println);
}
3 Lambda的不同用途
遍歷列表
public static void main(String[] args) {
List<String> fruits = List.of("mango", "oranges", "banana", "kiwi", "apple");
fruits.forEach(fruit -> System.out.println(fruit));
}
遍歷Map
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("value1", 10);
map.put("value2", 20);
map.put("value3", 30);
map.put("value4", 40);
map.forEach((key, value) -> System.out.println("key: " + key + ", value: " + value));
}
創(chuàng)建Runnable和Callable
Runnable是一個函數(shù)式接口,因此我們可以使用Lambda表達式來表示它。
使用匿名類創(chuàng)建Runnable的典型方式
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello World !");
}
};
}
同樣的Lambda表達式實現(xiàn)如下:
public static void main(String[] args) {
Runnable runnable = () -> System.out.println("Hello World !");
}
同樣地,Callable也可以實現(xiàn):
public static void main(String args[]) throws InterruptedException {
Callable<Integer> callable = () -> {
int sum = 0;
for (int i = 0; i < 5; i++) {
sum += i;
}
return sum;
};
}
Predicate
使用Lambda函數(shù)表示Predicate:
public class HelloWorld{
public static void main(String []args){
Predicate<Integer> predicate = (i) -> i > 10;
System.out.println(predicate.test(15));
}
}
Output: True
Consumer
使用Lambda函數(shù)表示Consumer:
public class HelloWorld{
public static void main(String []args){
//例1
Consumer<Integer> consumer = System.out::println;
consumer.accept(10);
//例2
List<String> inputs = new ArrayList<>();
Consumer<String> consumer = str -> inputs.add(str);
consumer.accept("first");
consumer.accept("second");
inputs.forEach(e -> System.out.println(e));
}
}
Example 1 output: 10,Example 2 output: first \n second
Comparator
Comparator是Java中的一個函數(shù)式接口,因此我們可以使用Lambda函數(shù)來表示它。
下面我們使用Lambda創(chuàng)建一個Comparator:
public static void process(List<Movie> movies) {
Comparator<Movie> movieComparator = (m1, m2) -> m1.getRating() - m2.getRating();
movies.sort(movieComparator);
}
讓我們看看更多的例子:
按自然順序排序數(shù)字列表:
private static void process(List<Integer> numbers) {
numbers.stream()
.sorted(Comparator.naturalOrder())
.forEach(System.out::println);
}
如果我們要根據(jù)多個參數(shù)對列表進行排序,則可以使用Comparator的thenComparing方法,如下所示:
private static void process(List<Movie> movies) {
movies.stream()
.sorted(Comparator.comparing(Movie::getName)
.thenComparing(Movie::getRating)
)
.forEach(System.out::println);
}
將排序后的列表反轉(zhuǎn):
private static void process(List<Movie> movies) {
movies.stream()
.sorted(Comparator.comparing(Movie::getName)
.thenComparing(Movie::getRating)
.reversed())
.forEach(System.out::println);
}
4 總結(jié)
本文中,我們探討了Lambda函數(shù),看了很多不同的Lambda函數(shù)的例子,我們還了解了如何使用方法引用和Comparator。