前言:
JDK1.8是2014年發布更新的新特性有、接口的更新、lambda表達式、方法的引用、Stream API、函數式接口、Hashorn、JavaFX、DateTime,同是出現了一種新的編程思想“函數式編程思想”,在早起我們接觸到Java中d的編程思想都是面向對象的編程思想,而面向對象強調的是“一切皆對象”,若果想要做什么事情,必須先構建對象,函數式編程思想則強調的是“做什么,而不是這都那么做”。
一、lambda表達式:
lambda表達式是JDK1.8中引進的一直一種編程思想,在有些情況下極大的簡化了java開發中的代碼編寫,下面來看一下傳統意義面向對象的寫法和lambda表達式編寫代碼的不同,以下分別以Runnable接口開啟一個線程為例:

public class test1 { public static void main(String[] args){ Runnable task = new Runnable() { public void run() { System.out.println("啟動線程"); } }; new Thread(task).start(); } }

public class test2 { public static void main(String[] args){ new Thread(() -> System.out.println("啟動線程")).start(); } }
上面test1啟動一個線程這里用的是匿名內部類的實現,創建一個Runnable實例交給Thread,而test2則是使用了lambda表達式的實現方式,可以看出lambda表達式的方式使原本復雜的代碼變得非常簡潔,而對於lambda表達式中的()、-> 等一些特殊符號代表的意思下面主要來看一下。
1:lambda表達式的標准格式。
在JDK1.8引入了lambda后,使用lambda表達式時,它是有一些特定的格式,這其中主要包含的一下幾點注意的地方:
(1)、一些參數:(如果參數有多個,如果參數沒有則留空)
(2)、一個箭頭:(箭頭在這里是固定的寫法)
(3)、箭頭后面代碼的具體實現:(大括號里面就是我們需要編寫的具體代碼)
具體來說就是:(參數類型 參數名稱,…………)-> { 具體的代碼實現 };來看一下一個無慘無返回值得lambda表達式的寫法,

public interface Lambda { void run(); }

public class test1 { public static void main(String[] args){ //lambda表達式方式 test(() -> {System.out.println("測試lambda表達式");}); } public static void test(Lambda lambda){ lambda.run(); } }
帶參且有返回值lambda表達式的寫法:

public interface Lambda { int run(int a, int b); }

public class test1 { public static void main(String[] args){ //lambda表達式方式 test((int a, int b) -> { System.out.println(a + b);return a + b;}); } public static void test(Lambda lambda){ lambda.run(3, 5); } }
2:lambda表達式的省略格式。
lambda表達式在編寫的過程中因為參數的不同等原因可以簡寫一些不需要的內容,就如上面剛開始的Runnable啟動線程的lambda編寫方式和測試中lambda編寫方式,其中Runnable的實現中沒有大括號,而這里其實是省略了大括號。
(1)、參數類型可以省略,但是只能同是省略所有參數類型,或者干脆都不省略,不能只是省略個別參數類型,如下省略int參數的類型。

public class test1 { public static void main(String[] args){ //lambda表達式方式 test(( a, b) -> { System.out.println(a + b);return a + b;}); } public static void test(Lambda lambda){ lambda.run(3, 5); } }
(2)、如果參數只有一個小括號可以省略。

public interface Lambda { int run(int a); }

public class test1 { public static void main(String[] args){ //lambda表達式方式 test( a -> {return a ;}); } public static void test(Lambda lambda){ lambda.run(3); } }
(3)、如果大括號之內的語句只有一個,那么無論是否有返回值,return、{}和分號都可以省略

public class test1 { public static void main(String[] args){ //lambda表達式方式 test( (a, b) -> a + b ); } public static void test(Lambda lambda){ lambda.run(3,5); } }
3:lambda表達式的使用前提條件:
在java中我們如果要想使用lambda表達式,lambda表達式不許要有上下文推導,簡單來說就是根據我們編寫的上下文推導出我們要調用的是哪個方法。
(1)、根據方法的參數推導得出lambda對應的接口,例如最開始Runnable啟動一個線程的lambda表達式的方式的寫法,Thread對象中需要傳入一個Runnable的實現,由此我們可以把之前的代碼改成如下寫法:

public class test2 { public static void main(String[] args){ new Thread(() -> System.out.println("啟動線程1")).start(); Runnable task = () -> System.out.println("啟動線程2"); new Thread(task).start(); } }
(2)、根據局部變量的賦值來推導出lambda對應的接口,也就是上面之前我們測試的那種寫法,寫一個方法吧接口類型當做參數傳入。
二、函數式接口的定義和使用:
在之前我們使用lambdab表達式時我們都需要定義一個接口,而我們定義的這個接口就是函數式接口,所謂的函數式接口就是支持函數式編程的接口,同時也就是支持lambda表達式的接口。
1、函數式接口的定義,有且只有一個抽象方法,但可以存在defult、static、private方法。
2、如果一個接口上面寫了@functionalInterface注解,此注解數用來檢測一個接口是否是函數式接口,並沒有其他的意義,如果不是函數式接口編譯檢測時會報錯。
三、lambda表達式和內部類的不同。
1、在這里強調一點,lambda表達式的寫法並不是“語法糖”,他與語法糖有着本質區別,語法糖只是讓代碼更加簡便,但底層實現原理並不會改變,列如方法中的可變參數、超級for循環等,他們的底層原理都是一個數組和迭代器。
2、所需類型不同:lambda表達式匿名內部類的實現,可以用接口、可以用抽象類也可以使用普通的類,而lambda表達式只能用接口。
3、使用限制不同:如果接口中只有一個抽象方法可以使用lambda表達式也可是使用匿名內部類,如果存在多個抽象方法則只能使用匿名內部類。
4、實現原理不同:匿名內部類就是一個類,編譯后會單獨的生成一個.class文件,lambda表達式編譯后丙類有.class文件,對應的字節碼則是在運行的時候才會生成:注:在java7中引入了invokedynamic指令,該指令的作用是允許程序運行后可以動態的生成一些字節碼,在這里就不如說是lambda表達式。