Java11已出,Java8已經是主流。
如今來一波操做,應該不會太遲(T_T)
注:本文持續更新 ^_^
本文主要介紹Java8的2大主要新特性lambda表達式和Stream API,2者提供了更高層次的抽象,簡化開發,提升生產效率。java
建立一個線程,使用了一個Runnable
匿名內部類程序員
Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("Hello Aron."); } });
看着問題不大,實際上弊端挺明顯:模板語法太多,真正有業務意義的的語句只有System.out.println("Hello Aron.")
,由於如此,也嚴重干擾了咱們閱讀代碼。編程
引入lambda
表達式後,則能夠這麼寫數組
Thread thread = new Thread(() -> System.out.println("Hello Aron."));
簡潔了太多,有木有?app
Runnable runnable = () -> System.out.println("Hello World."); Consumer<T> tConsumer = bean -> System.out.println("Hello World."); Runnable runnable1 = () -> { System.out.println("Hello World."); System.out.println("Hello World."); };
語法分爲3段式:參數 、->
以及語句,即(...)-> { ...}
ide
Java是強類型語言,方法參數都有固定的類型。那麼問題了,Lambda表達式,若是當作是一堆代碼片斷,也會表達一種明確的意圖,這個意圖,姑且能夠理解爲函數接口。函數
在編程過程當中,總會遇到不少函數接口,如下是JDK中一些比較最重要的函數接口線程
接口參數返回類型示例code
接口 | 參數 | 返回類型 | 示例 |
---|---|---|---|
Predicate<T> | T | boolean | 值等於「Hello」嗎? |
Consumer<T> | T | void | 輸出一個值 |
Function<T,R> | T | R | 獲取對象的一個屬性 |
Supplier<T> | None | T | 工廠方法 |
UnaryOperator<T> | T | T | 邏輯非(!) |
BinaryOperator<T> | (T, T) | T | 求2個數的和(+) |
先看一段熟悉的集合代碼對象
ArrayList<Java8Test> list = new ArrayList<>();
在ArrayList<Java8Test>
中申明瞭存儲的元素的類型,因而在ArrayList<>()
這裏的類型能夠缺省,編譯器能夠根據左側(即上文)推斷出來。
同理,在lambda表達式也是同樣的。
BinaryOperator<Long> addLongs = (x, y) -> x + y;
在上面的表達 式中,咱們注意到 (x, y)
這裏是沒有申明方法的參數類型的,卻能執行數學運算 +
。
這裏根據函數接口指定的泛型類爲Long
,便可推斷方法的參數爲Long
,而後執行x + y
。
Lambda
表達式是一個匿名方法,簡化了匿名內部類的寫法,把模板語法屏蔽,突出業務語句,傳達的更像一種行爲。Lambda
表達式是有類型的,JDK內置了衆多函數接口Lambda
的3段式結構:(...)-> { ...}
流(Stream)是Java8的新特性,是一種使程序員得以站在更高的抽象層次上對集合進行操做。在思路上,相似於SQL的存儲過程,有幾個步驟:
其中,第1步的定義操做叫惰性求值,給你套路(返回Stream
),可是不會執行返回結果。
第2步的觸發操做叫及早求值,這我的說幹就幹,立馬要結果(返回結果數據)。
第3步的篩選相似SQL的where
子句,對結果進一步的篩選。
Stream
類位於java.util.stream
包,是Java8核心的類之一,擁有衆多方法,下面羅列了一些比較重要的方法進行講解。更多的是拋磚引玉,任何教程都比不上本身的悟性來得爽快,先找點感受,先掌握基本用法嘗試使用起來,慢慢天然就會了。
要使用Stream
,那就必須得先建立一個String
類型的Stream
Stream<String> StrStream = Stream.of("a", "b");
使用收集器Collector
將StrStream
轉化爲熟悉的集合Collection
List<String> collect = StrStream.collect(Collectors.toList());
所謂map,從字面理解就是映射。這裏指的是對象關係的映射,
好比從對象集合映射到屬性結合:
List<String> names = Stream.of(new Student("zhangSan"), new Student("liSi")) .map(student -> student.getName()) .collect(toList());
從小寫字母映射到大寫字母:
List<String> collected = Stream.of("a", "b", "hello") .map(string -> string.toUpperCase()) .collect(toList());
將 字符串流 根據空格分割成 字符串數組流
Stream<String> stringStream = Stream.of("Hello Aron."); Stream<String[]> stringArrayStream = stringStream.map(word -> word.split(" "));
filter
顧名思義,過濾篩選。這裏的參數函數接口是一個條件,篩選出知足條件的元素
// 篩選年齡大於19的學生 List<Student> stu = Stream.of(new Student("zhangSan", 19), new Student("liSi"), 20) .filter(student -> student.getAge() > 19) .collect(toList());
flatMap
扁平化映射,即將數據元素爲數組的Stream
轉化爲單個元素
Stream<String> stringStream = Stream.of("Hello Aron."); // 返回值爲數組 Stream<String[]> stringArrayStream = stringStream.map(word -> word.split(" ")); // flatMap扁平化映射後,元素都合併了 Stream<String> flatResult = stringArrayStream.flatMap(arr -> Arrays.stream(arr))
max
即最大,相似SQL
中的函數max()
,從數據中根據必定的條件篩選出最值
// 篩選年齡最大/小的學生 Stream<Student> studentStream = Stream.of(new Student("zhangSam", 19), new Student("liSi", 20)); Optional<Student> max = studentStream.max(Comparator.comparing(student -> student.getAge())); // Optional<Student> max = studentStream.min(Comparator.comparing(student -> student.getAge())); // 年齡最大/小的學生 Student student = max.get();
reduce
操做實現從一組值中生成一個值,上面的max
、min
實際上都是reduce
操做。
參數Identity
表示初始值,
參數binaryOperator
是一個函數接口,表示二元操做,可用於數學運算
// 使用reduce() 求和 (不推薦生產環境使用) int count = Stream.of(1, 2, 3).reduce(0, (acc, element) -> acc + element);
上面代碼,展開reduce()
操做
BinaryOperator<Integer> accumulator = (acc, element) -> acc + element; int count = accumulator.apply( accumulator.apply(accumulator.apply(0, 1),2), 3);
// 查找全部姓張的同窗並按字典順序排序,存儲到list List<Student> newList = studentList.Stream() .filter(student -> student.getName().startsWith("張")) .sorted(Comparator.comparing(student -> student.getName()) .collect(toList());
以爲有用,記得收藏、點贊哦!