學習Stream的目的
-
函式式編程漸漸變成主流,為了看懂同事的代碼,
-
相對于傳統的編程方式,代碼更為簡潔清晰易懂,
-
使得并發編程變得如此簡單,
-
有效的避免了代碼嵌套地獄,(見樣例)
if (條件1) { if (條件2) { if (條件3) { // 再嵌套下去都快見到Diablo了, } } }
Stream的特點
- 不修改資料源:任何對于Stream物件的操作都不會修改資料源的資料,
- 延遲執行:中間操作只是對于一系列操作細節的定義,而非執行,只有在終端操作被呼叫的同時執行中間操作,
- 可消費:任何一個Stream物件執行了終端操作后都將不可再利用,只能操作由資料源生成的新的Stream,
Stream的分類
-
串行流:單項環境下的Stream,基礎,
List.of().stream(); -
并行流:多執行緒環境下的Stream,重點難點,本文中未涉及,
List.of().parallelStream();
Stream物件的創建
總共有三種方式:
-
經由集合物件創建
List<String> list = new ArrayList<>(); Stream<String> stream = list.stream(); -
經由陣列物件創建(兩種)
String[] strs = new String[10]; // 將陣列所有元素裝入stream Stream<String> stream1 = Arrays.stream(strs); // 將陣列指定區間的元素裝入stream Stream<String> stream2 = Arrays.stream(strs, 1, 7); -
使用Stream的靜態方法創建(三種)
// 由單個元素創建Stream,元素不允許為null Stream<String> stream1 = Stream.of("Test"); // 由單個元素創建stream,元素允許為null Stream<String> stream2 = Stream.ofNullable(null); // 由多個元素創建stream,內部其實呼叫的是Arrays.stream(T[] array) Stream<String> stream3 = Stream.of("Test1", "Test2", "Test3");
方法的分類
- 中間操作:根據呼叫的方法,回傳各種各樣的stream物件,傳入的各種Lambda只是修改了該物件中對應方法的定義,而非執行,
- 終端操作:執行終端操作的方法,并且其間也執行中間操作對應的方法,
常用方法(入門)
中間操作
distinct
方法簽名:Stream<T> distinct()
作用:回傳一個去重后的Stream,
List<String> list = List.of("1", "1");
list.stream().distinct()
.forEach(t -> System.out.println(t)); // 輸出:1
filter
方法簽名:Stream<T> filter(Predicate<? super T> predicate)
作用:回傳一個由滿足predicate條件的元素構成的Stream,
List<Integer> list = List.of(1, 3, 5);
list.stream().filter(t -> t >= 3)
.forEach(t -> System.out.println(t)); // 輸出:3, 5
sorted
因為sorted存在兩種多載,并且在jdk原始碼的實作并不相同,所以我們分開討論,
方法簽名:Stream<T> sorted()
作用:通過呼叫T型別重寫Comparable介面的compareTo方法排序,回傳排序后的Stream,
// 此處省略了一些java檔案定義的結構,請著眼于一下核心代碼
// NG例, 不實作Comparable介面
class MyInteger {
int value;
MyInteger(int value) {
this.value = https://www.cnblogs.com/buzuweiqi/p/value;
}
}
List list = new ArrayList<>();
list.add(new MyInteger(4));
list.add(new MyInteger(1));
list.add(new MyInteger(3));
list.stream().sorted() // 不報錯
.forEach(t -> System.out.println(t.value)); // ClassCastException:不能被強轉成Comparable型別
// OK例, 實作Comparable介面(Integer實作了Comparable介面)
List list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
list.stream().sorted()
.forEach(t -> System.out.println(t)); // 輸出:1 3 4
方法簽名:Stream<T> sorted(Comparator<? super T> comparator)
作用:通過呼叫傳入的comparator的compare方法排序,回傳排序后的Stream,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
list.stream().sorted((o1, o2) -> o2 - o1) // 傳入一個比較器的實作
.forEach(t -> System.out.println(t.value)); // 輸出:4 3 1
skip
方法簽名:Stream<T> skip(long n)
作用:回傳一個不包含前n項的Stream,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
list.stream().skip(2) // 跳過前兩個元素
.forEach(t -> System.out.println(t.value)); // 輸出:3
limit
方法簽名:Stream<T> limit(long n)
作用:回傳一個包含前n項的Stream,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
list.stream().limit(2) // 跳過前兩個元素
.forEach(t -> System.out.println(t.value)); // 輸出:4 1
peek
方法簽名:Stream<T> peek(Consumer<? super T> action)
作用:執行消費操作,回傳原Stream,雖然有消費操作,但是Stream的狀態并不會改變,并不會真正消費Stream這一特點是的peek方法常用于除錯,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
Stream<Integer> stream = list.stream();
stream.peek(t -> System.out.println(t)); // 輸出:4 1 3, 并且不消費stream
stream.forEach(t -> System.out.println(t)); // 輸出:4 1 3, 并且消費stream(消費后stream不可再次使用)
stream.forEach(t -> System.out.println(t)); // IllegalStateException:stream已經被操作或關閉
map
方法簽名:Stream<T> map(Function<? super T, ? extends R> mapper)
作用:將原Stream中的所有元素型別從T轉化為R(不是強轉,是通過一些操作得到R型別),回傳封裝R型別元素的Stream,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
list.stream().map(t -> String.valueOf(t)) // 將元素都轉換成String
.forEach(t -> System.out.println(t)); // 輸出:4 1 3
flatMap
方法簽名:Stream<T> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
作用:將原Stream中的所有元素型別從T轉化為R,回傳Stream<R>,與map的主要區別在于,適配一對多的資料型別,比如,型別T中存在一個List<String>,使用map回傳一個Stream<List<String>>,而是用flatMap則回傳一個Stream<String>,實作一對多的映射,
List<Integer[]> list = new ArrayList<>();
list.add(new Integer[] {1, 2, 3});
list.add(new Integer[] {4, 5, 3});
list.stream().flatMap(t -> Stream.of(t)) // 將各個陣列中的元素都放入stream, 實作 1 → n 的轉換
.forEach(t -> System.out.println(t)); // 輸出:1 2 3 4 5 3
終端操作
forEach
方法簽名:void forEach(Consumer<? super T> action)
作用:迭代消費Stream里的所有元素,比如列印,寫入檔案,寫入DB等,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
list.stream().forEach(t -> System.out.println(t)); // 輸出:4 1 3
toArray
方法簽名:Object[] toArray()
作用:將Stream中的所有元素封裝成Object[]回傳,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
Object[] objects = list.stream().toArray(); // 與元素型別無關, 固定回傳Object[]
Integer[] ints = (Integer[])objects; // 使用時你可能需要型別強轉
count
方法簽名:long count()
作用:回傳Stream中的元素個數,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
long count = list.stream().count(); // 回傳stream中的元素個數, 當前為3
findFirst
方法簽名:Optional<T> findFirst()
作用:Stream的第一個元素封裝在Optional中回傳,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
Optional<Integer> first = list.stream().findFirst(); // 回傳stream中的第一個元素, 當前為4
/*
Optional類內容比較多所以現在不做贅述, 大家姑且就認為是個只能存放一個元素的容器就好,以后會開一個新的博文詳細為 大家講解用法
*/
anyMatch
方法簽名:boolean anyMatch(Predicate<? super T> predicate)
作用:當存在符合predicate條件的元素時回傳true,否則回傳false,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
boolean bool = list.stream().anyMatch(t -> t <= 1); // 當一個元素小于等于1時就回傳true, 當前true
allMatch
方法簽名:boolean allMatch(Predicate<? super T> predicate)
作用:當所有元素都符合predicate條件時回傳true,否則回傳false,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
boolean bool = list.stream().allMatch(t -> t <= 1); // 當所有元素小于等于1時才回傳true, 當前false
noneMatch
方法簽名:boolean noneMatch(Predicate<? super T> predicate)
作用:當所有元素都不符合predicate條件時回傳true,否則回傳false,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
boolean bool = list.stream().noneMatch(t -> t <= 1); // 當所有元素都不小于等于1時才回傳true, 當前false
min
方法簽名:Optional<T> min(Comparator<? super T> comparator)
作用:按照傳入的比較器將最小的元素封裝在Optional中回傳,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
Optional<Integer> min = list.stream().min((o1, o2) -> o2 - o1); // 根據傳入的比較器實作回傳最小值, 當前4
/*
這個方法可以認為stream按照傳入的比較器排序, 回傳排序后的第一個元素
*/
max
方法簽名:Optional<T> max(Comparator<? super T> comparator)
作用:按照傳入的比較器將最大的元素封裝在Optional中回傳,
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(1);
list.add(3);
Optional<Integer> max = list.stream().max((o1, o2) -> o2 - o1); // 根據傳入的比較器實作回傳最大值
/*
這個方法可以認為stream按照傳入的比較器排序, 回傳排序后的最后一個元素
*/
本文只討論了串行流的使用方法,對于并行流等進階的使用方法請參考 Java -> Stream進階(尚未更新)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/502701.html
標籤:Java
上一篇:redis簡述
