前面積極響應讀者的需求,寫了兩篇Java新特性的文章。有小夥伴留言說:感受Lambda表達式很強大啊!一行代碼就可以搞定那麼多功能!我想學習下Lambda表達式的語法,能夠嗎?個人回答是:沒問題!這不,Lambda表達式來了!java
咱們先來看看從匿名類如何轉換到Lambda表達式呢?bash
這裏,咱們可使用兩個示例來講明如何從匿名內部類轉換爲Lambda表達式。微信
使用匿名內部類以下所示。ide
Runnable r = new Runnable(){ @Override public void run(){ System.out.println("Hello Lambda"); } }
轉化爲Lambda表達式以下所示。函數
Runnable r = () -> System.out.println("Hello Lambda");
使用匿名內部類做爲參數以下所示。學習
TreeSet<Integer> ts = new TreeSet<>(new Comparator<Integer>(){ @Override public int compare(Integer o1, Integer o2){ return Integer.compare(o1, o2); } });
使用Lambda表達式做爲參數以下所示。測試
TreeSet<Integer> ts = new TreeSet<>( (o1, o2) -> Integer.compare(o1, o2); );
從直觀上看,Lambda表達式要比常規的語法簡潔的多。code
Lambda表達式在Java語言中引入了 「->」 操做符, 「->」 操做符被稱爲Lambda表達式的操做符或者箭頭操做符,它將Lambda表達式分爲兩部分:對象
Lambda表達式本質上是對接口的實現,Lambda表達式的參數列表本質上對應着接口中方法的參數列表。blog
Lambda體本質上就是接口方法具體實現的功能。
咱們能夠將Lambda表達式的語法總結以下。
1.語法格式一:無參,無返回值,Lambda體只有一條語句
Runnable r = () -> System.out.println("Hello Lambda");
具體示例以下所示。
@Test public void test1(){ Runnable r = () -> System.out.println("Hello Lambda"); new Thread(r).start(); }
2.語法格式二:Lambda表達式須要一個參數,而且無返回值
Consumer<String> func = (s) -> System.out.println(s);
具體示例以下所示。
@Test public void test2(){ Consumer<String> consumer = (x) -> System.out.println(x); consumer.accept("Hello Lambda"); }
3.語法格式三:Lambda只須要一個參數時,參數的小括號能夠省略
Consumer<String> func = s -> System.out.println(s);
具體示例以下所示。
@Test public void test3(){ Consumer<String> consumer = x -> System.out.println(x); consumer.accept("Hello Lambda"); }
4.語法格式四:Lambda須要兩個參數,而且有返回值
BinaryOperator<Integer> bo = (a, b) -> { System.out.println("函數式接口"); return a + b; };
具體示例以下所示。
@Test public void test4(){ Comparator<Integer> comparator = (x, y) -> { System.out.println("函數式接口"); return Integer.compare(x, y); }; }
5.語法格式五:當Lambda體只有一條語句時,return和大括號能夠省略
BinaryOperator<Integer> bo = (a, b) -> a + b;
具體示例以下所示。
@Test public void test5(){ Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y); }
6.語法格式六:Lambda表達式的參數列表的數據類型能夠省略不寫,由於JVM編譯器可以經過上下文推斷出數據類型,這就是「類型推斷」
BinaryOperator<Integer> bo = (Integer a, Integer b) -> { return a + b; };
等同於
BinaryOperator<Integer> bo = (a, b) -> { return a + b; };
上述 Lambda 表達式中的參數類型都是由編譯器推斷得出的。 Lambda 表達式中無需指定類型,程序依然能夠編譯,這是由於 javac 根據程序的上下文,在後臺推斷出了參數的類型。 Lambda 表達式的類型依賴於上下文環境,是由編譯器推斷出來的。這就是所謂的「類型推斷」。
Lambda表達式須要函數式接口的支持,因此,咱們有必要來講說什麼是函數式接口。
只包含一個抽象方法的接口,稱爲函數式接口。
能夠經過 Lambda 表達式來建立該接口的對象。(若 Lambda表達式拋出一個受檢異常,那麼該異常須要在目標接口的抽象方法上進行聲明)。
能夠在任意函數式接口上使用 @FunctionalInterface 註解,這樣作能夠檢查它是不是一個函數式接口,同時 javadoc 也會包含一條聲明,說明這個接口是一個函數式接口。
咱們能夠自定義函數式接口,並使用Lambda表達式來實現相應的功能。
例如,使用函數式接口和Lambda表達式實現對字符串的處理功能。
首先,咱們定義一個函數式接口MyFunc,以下所示。
@FunctionalInterface public interface MyFunc <T> { public T getValue(T t); }
接下來,咱們定義一個操做字符串的方法,其中參數爲MyFunc接口實例和須要轉換的字符串。
public String handlerString(MyFunc<String> myFunc, String str){ return myFunc.getValue(str); }
接下來,咱們對自定義的函數式接口進行測試,此時咱們傳遞的函數式接口的參數爲Lambda表達式,而且將字符串轉化爲大寫。
@Test public void test6(){ String str = handlerString((s) -> s.toUpperCase(), "binghe"); System.out.println(str); }
運行test6方法,得出的結果信息以下所示。
BINGHE
咱們也能夠截取字符串的某一部分,以下所示。
@Test public void test7(){ String str = handlerString((s) -> s.substring(0,4), "binghe"); System.out.println(str); }
運行test7方法,得出的結果信息以下所示。
bing
能夠看到,咱們能夠經過handlerString(MyFunc<String> myFunc, String str)
方法結合Lambda表達式對字符串進行任意操做。
注意:做爲參數傳遞 Lambda 表達式:爲了將 Lambda 表達式做爲參數傳遞,接收Lambda 表達式的參數類型必須是與該 Lambda 表達式兼容的函數式接口的類型 。
若是以爲文章對你有點幫助,請微信搜索並關注「 冰河技術 」微信公衆號,跟冰河學習Java8新特性。
最後,附上Java8新特性核心知識圖,祝你們在學習Java8新特性時少走彎路。