java 8 stream

流的操做類型分爲兩種:java

  • Intermediate:一個流能夠後面跟隨零個或多個 intermediate 操做。其目的主要是打開流,作出某種程度的數據映射/過濾,而後返回一個新的流,交給下一個操做使用。這類操做都是惰性化的(lazy),就是說,僅僅調用到這類方法,並無真正開始流的遍歷。 map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered數組

  • Terminal:一個流只能有一個 terminal 操做,當這個操做執行後,流就被使用「光」了,沒法再被操做。因此這一定是流的最後一個操做。Terminal 操做的執行,纔會真正開始流的遍歷,而且會生成一個結果,或者一個 side effect forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator緩存

  • Short-circuiting:對一個無限及集合返回有限的數據 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limitbash

Filter

對象匹配過濾數據結構

方法 示意
filter 經過傳遞一個預期匹配的對象做爲參數並返回一個包含全部匹配到的對象的流。
distinct 返回包含惟一元素的流(惟一性取決於元素相等的實現方式)。
limit 返回一個特定上限的流
skip 返回一個丟棄前n個元素的流
List expensiveInvoices
= invoices.stream()
.filter(inv -> inv.getAmount() > 10_000)
.limit(5)
.collect(Collectors.toList());
複製代碼

Matching:

匹配是一個判斷是否匹配到給定屬性的廣泛的數據處理模式,表達式最後返回boolean架構

方法 示意
allMacth 流對象每一個都要匹配到
anyMatch 流對象有匹配到就中斷
noneMatch 流對象無匹配對象
boolean expensive =
invoices.stream()
.allMatch(inv -> inv.getAmount() > 1_000);
複製代碼

Finding

:流接口還提供了像findFirst和findAny等從流中取出任意的元素。它們能與像filter方法相鏈接。findFirst和findAny都返回一個可選對象,在串行流中二者都是返回第一個對象,在並行流中findAny返回第一個線程處理最快的數據app

方法 示意
findFirst 返回第一個匹配到的對象
findAny 返回第一個匹配到的對象
Optional =
invoices.stream()
.filter(inv ->
inv.getCustomer() == Customer.ORACLE)
.findAny();
複製代碼

Mapping

:流支持映射方法,傳遞一個函數對象做爲方法,把流中的元素轉換成另外一種類型。這種方法應用於單個元素,將其映射成新元素。框架

方法 示意
map 應用於單個元素,將其映射成新元素。
List ids
= invoices.stream()
.map(Invoice::getId)
.collect(Collectors.toList());
複製代碼

Reducing

方法 示意
reduce(BinaryOperator) 一個函數主要用於累和,求最大值。
int product = numbers.stream().reduce(1, (a, b) -> a * b);
int max = numbers.stream().reduce(Integer.MIN_VALUE,
Integer::max);
複製代碼

forEach,peek比較

forEach Terminal操做,再也不返回stream對象,forEach循環體內不能修改本身包含的本地變量值,也不能用 break/return 之類的關鍵字提早結束循環。 peek能夠對循環對象二次封裝並返回新的對象ide

sorted
它比數組的排序更強之處在於你能夠首先對 Stream 進行各種 map、filter、limit、skip 甚至 distinct 來減小元素數量後,再排序,這能幫助程序明顯縮短執行時間。函數

List<Person> persons = new ArrayList();
 for (int i = 1; i <= 5; i++) {
 Person person = new Person(i, "name" + i);
 persons.add(person);
 }
List<Person> personList2 = persons.stream().limit(2).sorted((p1, p2) -> p1.getName().compareTo(p2.getName())).collect(Collectors.toList());
System.out.println(personList2);
複製代碼

min/max/distinct(Terminal)

獲取最後計算的最小值,最大值和去重複

Collectors

目前爲止你所瞭解的方法都是返回另外一個流或者一個像boolean,int類型的值,或者返回一個可選對象。相比之下,collect方法是一個結束操做,它可使流裏面的全部元素彙集到彙總結果。 傳遞給collect方法參數是一個java.util.stream.Collector類型的對象。Collector對象實際上定義了一個如何把流中的元素彙集到最終結果的方法。最開始,工廠方法Collectors.toList()被用來返回一個描述瞭如何把流轉變成一個List的Collector對象。後來Collectors類又內建了不少類似的collectors變量。例如,你能夠用Collectors.groupingBy方法按消費者把發票分組

Map<Customer, List> customerToInvoices
= invoices.stream().collect(Collectors.group
ingBy(Invoice::getCustomer));
複製代碼

groupingBy/partitioningBy

Map<Integer, List<Person>> personGroups = Stream.generate(new PersonSupplier()).
 limit(100).
 collect(Collectors.groupingBy(Person::getAge));
Iterator it = personGroups.entrySet().iterator();
while (it.hasNext()) {
 Map.Entry<Integer, List<Person>> persons = (Map.Entry) it.next();
 System.out.println("Age " + persons.getKey() + " = " + persons.getValue().size());
}
複製代碼

在使用條件「年齡小於 18」進行分組後能夠看到,不到 18 歲的未成年人是一組,成年人是另一組。partitioningBy 實際上是一種特殊的 groupingBy,它依照條件測試的是否兩種結果來構造返回的數據結構,get(true) 和 get(false) 能即爲所有的元素對象。

map 處理的input和output一一對應

方法 示意
mapToInt 函數體返回值爲int類型
mapToDouble 函數體返回值爲Double類型。
mapToLong 函數體返回值爲Long類型。

flatMap 處理的input和outPut爲一對多關係

方法 示意
flatMapToInt 函數體返回值爲int類型
flatMapDouble 函數體返回值爲Double類型。
flatMapLong 函數體返回值爲Long類型。
Stream<List<Integer>> inputStream = Stream.of(
 Arrays.asList(1),
 Arrays.asList(2, 3),
 Arrays.asList(4, 5, 6)
 );
Stream<Integer> outputStream = inputStream.
flatMap((childList) -> childList.stream());
複製代碼

Parallel Streams

Stream API 支持方便的數據並行。換句話說,你能夠明確地讓流管道以並行的方式運行而不用關心底層的具體實現。在這背後,Stream API使用了Fork/Join框架充分利用了你機器的多核架構。 你所須要作的無非是用parallelStream()方法替換stream()方法。 不是全部的都使用並行的方式,以下

  • parallel streams的內部實現依賴於將數據結構劃分紅可讓不一樣線程使用的難易程度。像數組這種數據結構很容易劃分,而像鏈表或者文件這種數據結構很難劃分
  • 越是計算流中單個元素花費的資源最高,應用並行越有意義。
  • 若是可能的話儘可能用原始數據類型,這樣能夠佔用更少的內存,也更緩存命中率也更高。
  • 流中元素的數據量越大越好,由於並行的成本會分攤到全部元素,並行節省的時間相對會更多。固然,這也跟單個元素計算的成本相關。
  • 通常來講,核越多越好。
相關文章
相關標籤/搜索