lambda表達式簡介
個人理解,lambda表達式就是一種新的語法,沒有什么新奇的,簡化了開發者的編碼,其實底層還是一些常規的代碼。Lambda 是一個匿名函數,我們可以把 Lambda 表達式理解為是一段可以傳遞的代碼(將代碼像數據一樣進行傳遞)。可以寫出更簡潔、更靈活的代碼。作為一種更緊湊的代碼風格,使Java的語言表達能力得到了提升。
Lambda表達式的語法(記得要在jdk1.8及以上的jdk環境下實驗)
Lambda 表達式的基礎語法:Java8中引入了一個新的操作符 "->" 該操作符稱為箭頭操作符或 Lambda 操作符
箭頭操作符將 Lambda 表達式拆分成兩部分:
左側:Lambda 表達式的參數列表
右側:Lambda 表達式中所需執行的功能, 即 Lambda 體
語法格式一:無參數,無返回值
示例:
//平時的寫法
@Test
public void test1() {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("線程啟動了");
}
};
runnable.run();
}
/**
* 語法格式一:無參數,無返回值
* () -> System.out.println("Hello Lambda!");
*/
@Test
public void test2() {
//“->”左邊只有一個小括號,表示無參數,右邊是Lambda體(就相當於實現了匿名內部類里面的方法了,(即就是一個可用的接口實現類了。))
Runnable runnable = ()->System.out.println("線程啟動了");
runnable.run();
}
運行結果

語法格式二:有一個參數,並且無返回值
(x) -> System.out.println(x)
示例:
/**語法格式二:有一個參數,並且無返回值
* (x) -> System.out.println(x)
*/
@Test
public void test3() {
//這個e就代表所實現的接口的方法的參數,
Consumer<String> consumer = e->System.out.println("ghijhkhi"+e);
consumer.accept("woojopj");
}
Consumer的底層實現:
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.util.function;
import java.util.Objects;
/**
* Represents an operation that accepts a single input argument and returns no
* result. Unlike most other functional interfaces, {@code Consumer} is expected
* to operate via side-effects.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #accept(Object)}.
*
* @param <T> the type of the input to the operation
*
* @since 1.8
*/
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
/**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
結果:
語法格式三:若只有一個參數,小括號可以省略不寫 x -> System.out.println(x)</font(第二種方式的一種簡化吧)
語法格式四:有兩個以上的參數,有返回值,並且 Lambda 體中有多條語句
示例代碼:
@Test
public void test4() {
//Lambda 體中有多條語句,記得要用大括號括起來
Comparator<Integer> com = (x, y) -> {
System.out.println("函數式接口");
return Integer.compare(x, y);
};
int compare = com.compare(100, 244);
System.out.println(compare);
}
Comparator的底層相信大家都看過,是有一個compare()方法的。

運行結果:

語法格式五:若 Lambda 體中只有一條語句, return 和 大括號都可以省略不寫 即:Comparator
com = (x, y) -> Integer.compare(x, y);
語法格式六:Lambda 表達式的參數列表的數據類型可以省略不寫,因為JVM編譯器通過上下文推斷出,數據類型,即“類型推斷”(Integer x, Integer y) -> Integer.compare(x, y);
到這兒,相信大家也看出來規律了,這個Lambda表達式,好像離不開接口咦.......你還真說對了,這個Lambda表達式,是需要函數式接口的支持的,那么什么是函數式接口呢?
函數式接口 ,即只包含一個抽象方法的接口,稱為函數式接口。
你可以通過 Lambda 表達式來創建該接口的對象。(若 Lambda 表達式拋出一個受檢異常,那么該異常需要在目標接口的抽象方法上進行聲明)。
我們可以在任意函數式接口上使用 @FunctionalInterface 注解,這樣做可以檢查它是否是一個函數式接口,同時 javadoc 也會包含一條聲明,說明這個接口是一個函數式接口。像上面的Consumer接口就是一個函數式接口。
Java內置的四大函數式接口分別是:

consumer的上面已經演示過了。
下面是剩下的三個的
@Test
public void test6() {
Supplier<String> supplier = ()->"532323".substring(0, 2);
System.out.println(supplier.get());
}
@Test
public void test7() {
Function<String, String> function = (x)->x.substring(0, 2);
System.out.println(function.apply("我是中國人"));
}
@Test
public void test8() {
Predicate<String> predicate = (x)->x.length()>5;
System.out.println(predicate.test("12345678"));
System.out.println(predicate.test("123"));
}
運行結果

方法引用與構造器引用
方法引用
當要傳遞給Lambda體的操作,已經有實現的方法了,可以使用方法引用!
方法引用就是Lambda表達式,就是函數式接口的一個實例,通過方法的名字來指向一個方法,可以認為是Lambda表達式的一個語法糖。
要求:實現抽象方法的參數列表和返回值類型,必須與方法引用的方法的參數列表和返回值類型保持一致!
方法引用:使用操作符 “::” 將類(或對象) 與 方法名分隔開來。
如下三種主要使用情況:
對象::實例方法名
類::靜態方法名
類::實例方法名
"實現抽象方法的參數列表和返回值類型,必須與方法引用的方法的參數列表和返回值類型保持一致" 這句話很重要,一定要理解
我的理解是:
舉個例子
Comparator
Comparator
即:方法引用的方法是Integer的compare吧,他的參數列表是兩個integer類型,返回值是int,這個例子中的抽象方法是Comparator接口的compare()方法
public void test12() {
Comparator<Integer> comparator = (x,y)->Integer.compare(x, y);
Comparator<Integer> comparator1 = Integer::compare;
int compare = comparator.compare(1, 2);
int compare2 = comparator1.compare(1, 2);
System.out.println("compare:"+compare);
System.out.println("compare2:"+compare2);
}
運行結果
compare:-1
compare2:-1
