JavaSE JDK新特性
JDK8的新特性:
Lambda表達式與Functional接口
在JDK8之前,Java是不支持函數式編程的,所謂的函數編程,即可理解是將一個函數(也稱為“行為”)作為一個參數進行傳遞。通常我們提及得更多的是面向對象編程,面向對象編程是對數據的抽象(各種各樣的POJO類),而函數式編程則是對行為的抽象(將行為作為一個參數進行傳遞)。在JavaScript中這是很常見的一個語法特性,但在Java中將一個函數作為參數傳遞這卻行不通,好在JDK8的出現打破了Java的這一限制
Lambda表達式由3部分組成:
參數 -> 函數體
能夠接收Lambda表達式的參數類型,是一個只包含一個方法的接口。
package com.xk; /* *作者:吳誌龍 *日期:2018年8月17日 */ /** * 只有一個抽象方法的接口是函數式接口。 * @author 27783 * */ public interface Lambad { public void add(); }View Code
package com.xk; /* *作者:吳誌龍 *日期:2018年8月17日 */ public class LambadDemo { public static void test(Lambad lambad){ lambad.add(); }View Code//現在我要執行add方法但是我沒有實現類 //我們知道可以使用匿名內部類 public static void main(String[] args) { //匿名內部類的寫法 test(new Lambad() { @Override public void add() { System.out.println(10+5); } }); //使用lambad表達式test(() -> {System.out.println(10+5);}); } }
可以看到,只要是一個接口中只包含一個方法,則可以使用Lambda表達式,這樣的接口稱之為“函數接口”。
上面的函數接口比較簡單不包含參數,也不包含返回值
有參無返回值的:
package com.xk; /* *作者:吳誌龍 *日期:2018年8月17日 */ /** * 只有一個抽象方法的接口是函數式接口。 * @author 27783 * */ public interface Lambad { public void add(int a,int b); }View Code
package com.xk; /* *作者:吳誌龍 *日期:2018年8月17日 */ public class LambadDemo { public static void test(Lambad lambad){ int a=10;int b=20; lambad.add(a,b); } //現在我要執行add方法但是我沒有實現類 //我們知道可以使用匿名內部類 public static void main(String[] args) { //匿名內部類 test(new Lambad() { @Override public void add(int a, int b) { System.out.println(a+b); } }); //使用lambad表達式 test((a,b) ->{System.out.println(a+b);}); } }View Code
有參有返回值:
package com.xk; /* *作者:吳誌龍 *日期:2018年8月17日 */ /** * 只有一個抽象方法的接口是函數式接口。 * @author 27783 * */ public interface Lambad { public int add(int a,int b); }View Code
package com.xk; /* *作者:吳誌龍 *日期:2018年8月17日 */ public class LambadDemo { public static int test(Lambad lambad){ int a=10;int b=20; int c=lambad.add(a,b); return c; } //現在我要執行add方法但是我沒有實現類 //我們知道可以使用匿名內部類 public static void main(String[] args) { //匿名內部類 test(new Lambad() { @Override public int add(int a, int b) { return a+b; } }); //使用lambad表達式 int c=test((a,b) -> {return a+b;} ); System.out.println(c); } }View Code
使用泛型:
package com.xk; /* *作者:吳誌龍 *日期:2018年8月17日 */ /** * 只有一個抽象方法的接口是函數式接口。 * @author 27783 * */ public interface Lambad<T> { public int add(T a,T b); }View Code
package com.xk; /* *作者:吳誌龍 *日期:2018年8月17日 */ public class LambadDemo { public static int test(Lambad<Integer> lambad){ int a=10;int b=20; int c=lambad.add(a,b); return c; } //現在我要執行add方法但是我沒有實現類 //我們知道可以使用匿名內部類 public static void main(String[] args) { // //匿名內部類 // test(new Lambad<Integer>() { // // @Override // public int add(Integer a, Integer b) { // // TODO Auto-generated method stub // return a+b; // } // }); //使用lambad表達式 int c=test((Integer a, Integer b) -> {return a+b;} ); System.out.println(c); } }View Code
使用泛型後,在我們使用的時候,註意要設置參數的類型,不設置的化,系統會自動根據上下文來推導這個數據類型,但是最好還是寫上。
這三種基本情況已經大致清楚了,特別是需要弄清,什麽時候可以使用Lambda表達式代替匿名內部類,也就是Lambda表達式的應用場景是函數接口。Lambda表達式這一新特性在JDK8中的引入,更大的好處則是集合API的更新,新增的Stream類庫,使得我們在遍歷使用集合時不再像以往那樣不斷地使用for循環
stream:
在jdk8中引入了新的概念:
流是Java8引入的全新概念,它用來處理集合中的數據,我們可以把他理解為一種高級集合。
我們知道集合的一些操作很麻煩,需要寫大量的代碼 而流是以聲明的形式操作集合,它就像SQL語句,我們只需告訴流需要對集合進行什麽操作,它就會自動進行操作,並將執行結果交給你,無需我們自己手寫代碼。
因此,流的集合操作對我們來說是透明的,我們只需向流下達命令,它就會自動把我們想要的結果給我們。由於操作過程完全由Java處理,因此它可以根據當前硬件環境選擇最優的方法處理,我們也無需編寫復雜又容易出錯的多線程代碼了。
流的特點:
只能遍歷一次。流在使用一次後就會關閉了,我們無法進行下一次操作了。當然我們可以重新去開始一個流,進行操作。
采用內部叠代方式。若要對集合進行處理,則需我們手寫處理代碼,這就叫做外部叠代。而要對流進行處理,我們只需告訴流我們需要什麽結果,處理過程由流自行完成,這就稱為內部叠代。
流的操作分為兩種,分別為中間操作 和 終端操作。
-
中間操作
當數據源中的數據上了流水線後,這個過程對數據進行的所有操作都稱為“中間操作”。
中間操作仍然會返回一個流對象,因此多個中間操作可以串連起來形成一個流水線。 -
終端操作
當所有的中間操作完成後,若要將數據從流水線上拿下來,則需要執行終端操作。
終端操作將返回一個執行結果,這就是你想要的數據。
流的操作過程
使用流一共需要三步:
- 準備一個數據源
- 執行中間操作
中間操作可以有多個,它們可以串連起來形成流水線。 - 執行終端操作
執行終端操作後本次流結束,你將獲得一個執行結果。
流的使用:
在使用流之前,首先需要擁有一個數據源,並通過StreamAPI提供的一些方法獲取該數據源的流對象。數據源可以有多種形式:集合、數組、多個值、文件。
package com.xk; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; /* *作者:吳誌龍 *日期:2018年8月17日 */ public class StreamDemo { //Stream的一些操作 public static void main(String[] args) { //集合獲取流 List<Integer> list = new ArrayList<Integer>(); Stream<Integer> stem=list.stream(); //數組獲取流 String[] name={"悟空","八戒","悟凈"}; Stream<String> result=Arrays.stream(name); //值獲取流 Stream<String> ste = Stream.of("悟空","八戒","悟凈"); //文件操作獲取流 try { Stream stream=Files.lines(Paths.get("路徑名")); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }View Code
流的操作:這裏我們主要使用集合操作。
package com.xk; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; /* *作者:吳誌龍 *日期:2018年8月17日 */ public class StreamTest { public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); // 篩選操作:filter List<Integer> result = list.stream().filter(temp -> temp < 10).collect(Collectors.toList()); // 去重 List<Integer> result = list.stream().distinct().collect(Collectors.toList()); // 截取:截取多少個元素:最大不能超過 list.size(); List<Integer> result = list.stream().limit(5).collect(Collectors.toList()); // 跳過多少個元素 List<Integer> result = list.stream().skip(4).collect(Collectors.toList()); } }View Code
package com.xk; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; /* *作者:吳誌龍 *日期:2018年8月17日 */ public class StreamTest { public static void main(String[] args) { List<Student> list = new ArrayList<Student>(); Student student1 = new Student("八戒", 500); Student student = new Student("悟空", 500); Student student2 = new Student("悟靜", 500); list.add(student1); list.add(student); list.add(student2); // 對流中的每個元素執行一個函數, // 使得元素轉換成另一種類型輸出。 // 流會將每一個元素輸送給map函數, // 並執行map中的Lambda表達式, // 最後將執行結果存入一個新的流中 List<String> result = list.stream().map(Student::getName).collect(Collectors.toList()); result.forEach(temp -> { System.out.println(temp); }); // 是否匹配任一元素 // anyMatch用於判斷流中是否存在至少一個元素滿足指定的條件, // 這個判斷條件通過Lambda表達式傳遞給anyMatch,執行結果為boolean類型 boolean flag = list.stream().anyMatch((temp) -> temp.getName().equals("悟空")); System.out.println(flag); // findAny能夠從流中隨便選一個元素出來,它返回一個Optional類型的元素。 Optional<Student> option = list.stream().findAny(); } }View Code
Optional介紹
Optional是Java8新加入的一個容器,這個容器只存1個或0個元素,它用於防止出現NullpointException,它提供如下方法:
- isPresent()
判斷容器中是否有值。 - ifPresent(Consume lambda)
容器若不為空則執行括號中的Lambda表達式。 - T get()
獲取容器中的元素,若容器為空則拋出NoSuchElement異常。 - T orElse(T other)
獲取容器中的元素,若容器為空則返回括號中的默認值
JavaSE JDK新特性