45分鐘學會Java8 - Lambda和Stream

Java11已出,Java8已經是主流。
如今來一波操做,應該不會太遲(T_T)
注:本文持續更新 ^_^

1. 前言

本文主要介紹Java8的2大主要新特性lambda表達式和Stream API,2者提供了更高層次的抽象,簡化開發,提升生產效率。java

2. Lambda表達式

2.1 初識Lambda表達式

建立一個線程,使用了一個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

2.2 更多Lambda表達式

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

2.3 函數接口

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個數的和(+)

2.4 類型推斷

先看一段熟悉的集合代碼對象

ArrayList<Java8Test> list = new ArrayList<>();

ArrayList<Java8Test>中申明瞭存儲的元素的類型,因而在ArrayList<>()這裏的類型能夠缺省,編譯器能夠根據左側(即上文)推斷出來。

同理,在lambda表達式也是同樣的。

BinaryOperator<Long> addLongs = (x, y) -> x + y;

在上面的表達 式中,咱們注意到 (x, y)這裏是沒有申明方法的參數類型的,卻能執行數學運算 +

這裏根據函數接口指定的泛型類爲Long,便可推斷方法的參數爲Long,而後執行x + y

2.5 Lambda小結

  • Lambda表達式是一個匿名方法,簡化了匿名內部類的寫法,把模板語法屏蔽,突出業務語句,傳達的更像一種行爲。
  • Lambda表達式是有類型的,JDK內置了衆多函數接口
  • Lambda的3段式結構:(...)-> { ...}

3. Stream 流

3.1 簡介

流(Stream)是Java8的新特性,是一種使程序員得以站在更高的抽象層次上對集合進行操做。在思路上,相似於SQL的存儲過程,有幾個步驟:

  1. 先定義一些操做的集合,注意:這裏只定義,不真正執行
  2. 觸發執行,獲取結果
  3. 對結果進一步處理,篩選、打印、使用

其中,第1步的定義操做叫惰性求值,給你套路(返回Stream),可是不會執行返回結果。

第2步的觸發操做叫及早求值,這我的說幹就幹,立馬要結果(返回結果數據)。

第3步的篩選相似SQL的where子句,對結果進一步的篩選。

3.2 Stream API

Stream 類位於java.util.stream包,是Java8核心的類之一,擁有衆多方法,下面羅列了一些比較重要的方法進行講解。更多的是拋磚引玉,任何教程都比不上本身的悟性來得爽快,先找點感受,先掌握基本用法嘗試使用起來,慢慢天然就會了。

3.2.1 Stream.of(T… t)

要使用Stream,那就必須得先建立一個String類型的Stream

Stream<String> StrStream = Stream.of("a", "b");

3.2.2 Stream.collect(Collector<? super T, A, R> collector)

使用收集器CollectorStrStream轉化爲熟悉的集合Collection

List<String> collect = StrStream.collect(Collectors.toList());

3.2.2 Stream.map(Function<? super T, ? extends R> mapper)

所謂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(" "));

3.2.3 Stream.filter(Predicate<? super T> predicate)

filter顧名思義,過濾篩選。這裏的參數函數接口是一個條件,篩選出知足條件的元素

// 篩選年齡大於19的學生
List<Student> stu = Stream.of(new Student("zhangSan", 19), new Student("liSi"), 20)
                        .filter(student -> student.getAge() > 19)
                        .collect(toList());

3.2.4 Stream.flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)

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))

3.2.5 Stream.max(Comparator<? super T> comparator)

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();

3.2.7 Sream.reduce(T identity, BinaryOperator<T> binaryOperator)

reduce操做實現從一組值中生成一個值,上面的maxmin實際上都是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);

3.2.8 綜合操做

// 查找全部姓張的同窗並按字典順序排序,存儲到list
List<Student> newList = studentList.Stream()
            .filter(student -> student.getName().startsWith("張"))
            .sorted(Comparator.comparing(student -> student.getName())
            .collect(toList());
以爲有用,記得收藏、點贊哦!
相關文章
相關標籤/搜索