Intermediate :
一個流可以後面跟隨零個或多個 intermediate 操作。其目的主要是打開流,做出某種程度的數據映射/過濾,然後返回一個新的流,交給下一個操作使用。這類操作都是惰性化的(lazy),就是說,僅僅調用到這類方法,並沒有真正開始流的遍歷。
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel(並行)、 sequential、 unordered
map (對元素進行處理並返回處理結果)
Stream<Integer> simpleStream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
//Intermediate(媒介) 惰性求值方法(N)
simpleStream.map(x->x+5+"\t").forEach(System.out::print);
控制檯輸出
mapToInt、mapToLong、mapToDouble 都是在map方法的基礎上返回對應類型的專業化流
//在map操作的基礎上返回該數據類型對應的專業化Stream
IntStream intStream = simpleStream.mapToInt(x -> x + 5);
DoubleStream doubleStream = simpleStream.mapToDouble(x -> x + 5);
LongStream longStream = simpleStream.mapToLong(x -> x + 5);
例:小寫元素轉大寫
//小寫元素轉大寫
Stream<String> stringStream = Stream.of("a", "b", "c", "d");
//stringStream.map(x->x.toUpperCase()).forEach(System.out::println);
//可簡寫
stringStream.map(String::toUpperCase).forEach(System.out::println);
filter(過濾)
//filter 依據lambda過濾Stream元素
long count = simpleStream.filter(x -> x > 4).count();
System.out.println(count);
distinct(元素去重)
//distinct 元素去重,對於有序流不影響其排序
Stream<Integer> distinctStream = Stream.of(1, 2, 3, 4, 4, 4, 4, 5, 6, 7, 8, 9);
distinctStream.distinct().map(x->x+"\t").forEach(System.out::print);
控制檯輸出
sorted(元素排序)
//sorted 元素排序,按照自然循序或compare規則排序
//自然順序排序
Stream<Integer> sortedStream = Stream.of(1, 5, 9, 7, 3, 6, 4, 8, 2,0);
sortedStream.sorted().map(x->x+"\t").forEach(System.out::print);
System.out.println();
//倒序
Stream<Integer> sortedStream1 = Stream.of(1, 5, 9, 7, 3, 6, 4, 8, 2,0);
sortedStream1.sorted(Comparator.reverseOrder()).map(x->x+"\t").forEach(System.out::print);
控制檯輸出
limit(截取前N個元素)
//返回由此流的元素組成的流,截短長度不要超過maxSize 。
Stream<Integer> limitStream = Stream.of(1, 5, 9, 7, 3, 6, 4, 8, 2,0);
limitStream.limit(3).map(x->x+"\t").forEach(System.out::print);
控制檯輸出
skip(截取後N個元素)
//在丟棄流的第一個n元素後,返回由該流的剩餘元素組成的流。 如果此流包含少於n元素,那麼將返回一個空流。
Stream<Integer> skipStream = Stream.of(1, 5, 9, 7, 3, 6, 4, 8, 2,0);
skipStream.skip(3).map(x->x+"\t").forEach(System.out::print);
控制檯輸出
Terminal :
一個流只能有一個 terminal 操作,當這個操作執行後,流就被使用“光”了,無法再被操作。所以這必定是流的最後一個操作。Terminal 操作的執行,纔會真正開始流的遍歷,並且會生成一個結果,或者一個 side effect。
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
forEach/forEachOrder(遍歷)
forEach是並行處理的,forEachOrder是按順序處理的,顯然前者速度更快。
toArray(返回一個數組對象)
//toArray
Stream<Integer> arrayStream = Stream.of(1, 5, 9, 7, 3, 6, 4, 8, 2,0);
//無參,返回一個Object數組
Object[] objects = arrayStream.toArray();
//發生器函數採用一個整數,它是所需數組的大小,併產生一個所需大小的數組
//構造引用 ,限定返回數組類型
String[] strings = arrayStream.toArray(String[]::new);
reduce(累積-減少,總和,最小,最大,平均和字符串連接等)
F//reduce 減少操作
//T reduce(T identity,BinaryOperator<T> accumulator)
// 使用提供的身份值和associative累積功能對此流的元素執行reduction ,並返回減小的值
IntStream range = IntStream.rangeClosed(1, 10);
int reduce = range.reduce(0, Integer::sum);
System.out.println(reduce);
//等價於
IntStream range1 = IntStream.rangeClosed(1, 10);
int reduce1 = range1.reduce(0, (a, b) -> a + b);
System.out.println(reduce1);
//Optional<T> reduce(BinaryOperator<T> accumulator)
IntStream range2 = IntStream.rangeClosed(1, 10);
OptionalInt reduce2= range2.reduce((a, b) -> a + b);
int asInt = reduce2.getAsInt();
System.out.println(asInt);
collect (將Stream轉換爲其他數據結構)
//collect 將Stream轉換爲其他數據結構
//提供了兩個重載的方法
//<R> R collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)
//supplier:一個能創造目標類型實例的方法。
// accumulator:一個將當元素添加到目標中的方法。
// combiner:一個將中間狀態的多個結果整合到一起的方法(併發的時候會用到)
IntStream stream = Arrays.stream(range(1, 10).toArray());
ArrayList<Object> collect = stream.collect(ArrayList::new, List::add, List::addAll);
System.out.println(collect.toString());
//<R,A> R collect(Collector<? super T,A,R> collector)
//注:Stream的特化IntStream,LongStream,DoubleStream不具備該方法
List<String> strings = Arrays.asList("a", "b", "c", "d", "e");
//可以通過Collectors提供的靜態方法返回各種數據,其實就是另一個方法的封裝簡化
//List->Set
Set<String> collect1 = strings.stream().collect(Collectors.toSet());
System.out.println(collect1.toString());
//List->Map
Map<String, String> collect3 = strings.stream().collect(Collectors.toMap(x -> x.toUpperCase(), y -> y.toString()));
System.out.println(collect3.toString());
anyMatch/allMatch/noneMatch (是否滿足條件)
IntStream stream1 = Arrays.stream(range(1, 10).toArray());
//anyMatch 表示,判斷的條件裏,任意一個元素成功,返回true
System.out.println(stream1.anyMatch(x->x>5)); //返回true
//allMatch 表示,判斷條件裏的元素,所有的都是,返回true
System.out.println(stream1.allMatch(x->x>0)); //返回true
//noneMatch 跟allMatch相反,判斷條件裏的元素,所有的都不是,返回true
System.out.println(stream1.noneMatch(x->x<0)); //返回true
Short-circuiting :
- 於一個 intermediate 操作,如果它接受的是一個無限大(infinite/unbounded)的 Stream,但返回一個有限的新 Stream。
- 對於一個 terminal 操作,如果它接受的是一個無限大的 Stream,但能在有限的時間計算出結果。
當操作一個無限大的 Stream,而又希望在有限時間內完成操作,則在管道內擁有一個 short-circuiting 操作是必要非充分條件。
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit