Stream中的常用操作詳解
java8 Stream中的常用操作
一. 匹配、過濾、篩選操作
- 以下操作的入引數都是Predicate[核心是輸入一個值,返回一個布林值(true or false)].
- 流的中間操作和終止操作,簡單理解就是終止操作之後返回的不是流物件(其他物件或沒有返回值),中間操作返回的都是流物件(Stream
)。 - 具體的操作案例
-
filter: 是一種流的中間操作
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); stringList.stream() .filter(x -> x.length() > 3) .forEach(System.out::println);
-
anyMatch 是一種流的終止操作,與此用法相同的還有一個allMatch 和noneMatch,也是終止操作,區別是allMatch是所有匹配才返回true,anyMath是隻要有一個匹配就返回true, noneMatch 是沒有匹配到返回true。
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); boolean match = stringList.stream().anyMatch(x -> x.contains("c")); System.out.println(match); boolean allMatch = stringList.stream().allMatch(x -> x.contains("c")); System.out.println(allMatch); boolean noMatch = stringList.stream().allMatch(x -> x.contains("c")); System.out.println(noMatch);
-
dropWhile: 刪除當前流中符號條件的資料,直到不滿足條件為止,即從流中的第一個元素開始匹配,如果滿足則繼續匹配,如果不滿足就不會再繼續象後匹配。
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); stringList.stream() //匹配第一個元素是滿足條件的,第二個不滿足條件,後續就算是滿足條件的也不會被刪除 .dropWhile(x -> x.length() < 5) .forEach(System.out::println); stringList.stream() //匹配第一個元素是不滿足條件的,後續就算是滿足條件的也不會被刪除 .dropWhile(x -> x.length() < 3) .forEach(System.out::println);
-
takeWhile 與dropWhile類似,只是takeWhile是取出來元素生成新的流,dropWhile是刪除匹配的元素,用剩下的元素生成一個新的流
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); stringList.stream() //匹配時前兩個滿足,第三個不滿足就會終止,即只取到前面兩個元素 .takeWhile(x -> x.length() > 2) .forEach(System.out::println);
二. map相關操作
- map操作傳入的引數是Function[核心是輸入一個引數,返回一個值],map也是流的中間操作,map結果是一個新流
- 如果結果為空,則返回空流(empty stream)
- 具體的操作案例
- map
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php");
stringList.stream()
.filter(x -> x.length() > 3)
.map(String::length)
.forEach(System.out::println);
//- mapToInt 即通過一個ToIntFunction,返回一個IntStream
//- mapToDouble 即通過一個ToDoubleFunction,返回一個DoubleStream
//- mapToLong 即通過一個ToLongFunction,返回一個LongStream
- flatmap
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php");
stringList.stream()
.flatMap(x -> Stream.of(x.split("")))
.forEach(System.out::println);
//- flatMapToInt 即通過一個Function,返回一個IntStream
//- flatMapToDouble 即通過一個Function,返回一個DoubleStream
//- flatMapToLong 即通過一個Function,返回一個LongStream
三.排序、最值、去重操作
-
排序有兩個方法,sorted()和sorted(Comparator<? super T> comparator),前者是預設排序,後者是按特定的比較器實現排序,排序也是一種中間操作
-
max和min是兩個求最值的操作,是一種流的終止操作,返回的是一個最值得Optional
-
去重是distinct操作,也是中間操作
-
案例:
- sorted
//sorted List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); stringList.stream() .sorted() .forEach(System.out::println); //特定比較器排序 stringList.stream() //Comparator.comparingInt(String::length) 等價於lambada表示式:(x,y) -> x.length() - y.length() .sorted(Comparator.comparingInt(String::length)) .forEach(System.out::println);
- max、min 都是傳入一個比較器,返回一個對應得Optional
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); String val = stringList.stream() //換成min也同理 .max(Comparator.comparingInt(String::length)) .orElse(null); System.out.println(val);
- distinct
List<String> strList = List.of("java","pathon", "go", "c++", "c#", "php", "java", "go"); strList.stream().distinct().forEach(System.out::println);
四. 數量相關操作
-
計數操作:count終止操作,返回的是當前流中的元素個數
-
跳過操作:skip 中間操作,返回當前流中跳過指定元素個數後剩下的元素組成的新流
-
取數操作:limit 中間操作,返回當前流中前n個元素組成的新的流,n為正整數 是limit函式的引數
-
案例
-
count
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); long count = stringList.stream().filter(x -> x.length() > 3).count(); System.out.println(count);
-
skip
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); stringList.stream().skip(2).forEach(System.out::println);
-
limit
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); stringList.stream().limit(2).forEach(System.out::println);
-
五.查詢操作(findAny和findFirst)
-
查詢操作都屬於終止操作,都無入參
-
一般搭配篩選和過濾等中間操作
-
案例
-
findFirst
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); String val = stringList.stream() .findFirst() .orElse(null); System.out.println(val); //搭配filter,sorted String value = stringList.stream() .filter(x -> x.length() > 2) .sorted() .findFirst() .orElse(null); System.out.println(value);
-
findAny
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); String val = stringList.stream() .findAny() .orElse(null); System.out.println(val); //搭配filter,sorted String value = stringList.stream() .filter(x -> x.length() > 2) .sorted() .findAny() .orElse(null); System.out.println(value);
-
六.遍歷操作(peek和foreach)
-
peek是中間操作,一般用於程式除錯,最終結果是一個流物件
-
foreach是終止操作,無返回值
-
案例
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); stringList.stream() .peek(System.out::println) .filter(x -> x.length() > 4) .forEach(System.out::println);
七. collect操作
-
collect操作有兩個方法,一個是collect(Collector<? super T, A, R> collector), 一個是collect(Supplier
supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner)。 -
Collector<? super T, A, R> collector 是一個介面,該介面對應方法有以下幾個
-
Supplier supplier(); 即生成一個型別為A的可變容器
-
BiConsumer<A, T> accumulator(); 可變容器的具體操作
-
BinaryOperator combiner(); 合併函式
-
Function<A, R> finisher(); 最終結果轉換函式
-
-
常用操作案例
List<String> stringList = List.of("java","pathon", "go", "c++", "c#", "php"); //toList List<String> list = stringList.stream() .filter(x -> x.length() > 4) .collect(Collectors.toList()); //toSet Set<String> set = stringList.stream() .filter(x -> x.length() > 4) .collect(Collectors.toSet()); //toMap Map<String, Integer> map = stringList.stream() .filter(x -> x.length() > 4) .collect(Collectors.toMap(x -> x, String::length)); //joining String str = stringList.stream() .filter(x -> x.length() > 4) .collect(Collectors.joining(",")); String str2 = stringList.stream() .filter(x -> x.length() > 4) .collect(Collectors.joining(",","{","}")); //groupingBy List<String> strList = List.of("java","pathon", "go", "c++", "c#", "php", "java", "go"); Map<String, List<String>> listMap = strList.stream() .collect(Collectors.groupingBy(x -> x)); //partitioningBy List<String> strList = List.of("java","pathon", "go", "c", "c", "php", "java", "go"); Map<Boolean, List<String>> booleanListMap =strList.stream() .collect(Collectors.partitioningBy(x -> x.contains("c"))); //一般操作 即用指定的函式實現Collectors操作 List<String> strList = List.of("java","pathon", "go", "c", "c", "php", "java", "go"); List<String> list = strList.stream() .distinct() .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
八. reduce操作
-
reduce 操作實現的是從通過當前流中元素根據指定的計算生成一個新的值,計算可以是count、min和max等方法,概念比較抽象,多練習。
-
reduce和collect一樣都有一般操作,兩者類似,就是按照對應的介面實現來完成相應的操作。
-
常用案例
// 用reduce(BinaryOperator<T> accumulator) BinaryOperator是傳入兩個相同的值,返回一個跟入參型別一樣的值,此方法返回的是Optional List<String> strList = List.of("java","pathon", "go", "c", "c", "php", "java", "go"); String reduce = strList.stream().reduce((x, y) -> x + y).orElse(""); //用reduce(T identity, BinaryOperator<T> accumulator) 此方法返回指定型別T的值,即在指定型別T,值為identity的基礎上進行對應的操作後得到的結果,BinaryOperator是輸入兩個入參型別都為T,返回值也為T String reduce1 = strList.stream().reduce("@@@", (x, y) -> x + y); //用reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) 此方法返回的是指定型別U的值,BiFunction<U, ? super T, U> 其核心為輸入兩個值U,T,返回的是入參中的U int reduce2 = strList.stream() .reduce(0, (x, y) -> x + y.length(), Integer::sum);
stream的建立見之前的基礎篇,後續再詳解函數語言程式設計介面,這塊內容後續也會涉及Flux,Spring Web Flux。