Java 8 新特性——Stream API
目錄
Stream API(java.util.stream.*)。
Stream是Java8中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的操作,可以執行非常複雜的查詢、過濾和對映資料等操作。使用Stream API對集合資料進行操作,就類似於使用SQL執行的資料庫查詢。也可以使用Stream API·來並行操作。簡而言之,Stream API提供了一種高效且易於使用的處理資料的方式。
1. 什麼是stream
是資料渠道,用於操作源(集合、組等)所生成的元素序列。
“集合講的是資料,流講的是計算!”
注意:
- Stream 自己不會儲存元素。
- Stream 不會改變源物件。相反,他們會返回一個持有結果的新Stream。
- Stream 操作是延遲執行的。這意味著他們會等到需要結果的時候才執行。
2. Stream操作三個步驟
· 建立Stream 一個數據源(如:集合、陣列),獲取一個流
· 中間操作 一箇中間操作鏈,對資料來源的資料進行處理
· 終止操作(終端操作)
3. 建立Stream
// Java8 中的Collection介面被擴充套件,提供了兩個獲取流的方法: default Stream<E> stream() // 返回一個順序流 default Stream<E> parallelStream() // 返回一個並行流 // -- 由陣列建立流 // Java8 中的Arrays 的靜態方法stream() 可以獲取陣列流: static <T> Stream<T> stream(T[] array) // 返回一個流 // 過載形式,能夠處理對應基本型別的陣列: public static IntStream stream(int[] array) public static LongStream stream(long[] array) public static DoubleStream stream(double[] array) // -- 由值建立流 // 可以使用靜態方法Stream.of(),通過顯示值建立一個流。它可以接收任意數量的引數。 public static<T> Stream<T> of(T… values) // 返回一個流 // -- 由函式建立流:建立無限流 // 可以使用靜態方法Stream.iterate() 和Stream.generate(),建立無限流。 // 迭代 Public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) // 生成 Public static<T> Stream<T> generate(Supplier<T> s)
4. Stream 的中間操作
多個中間操作可以連線起來形成一個流水線,除非流水線上觸發終止操作,否則中間操作不會執行任何的處理!而在終止操作時一次性全部處理,稱為“惰性求值”。
篩選與切片
方法 |
描述 |
Filter(Predicate p) |
接收Lambda,從流中排除某些元素。 |
Distinct() |
篩選,通過流所生成元素的hashCode()和equals()去除重複元素 |
Limit(long maxSize) |
截斷流,使其元素不超過給定數量 |
Skip(long n) |
跳過元素,返回一個扔掉了前n個元素的流。若流中元素不足n個,則返回一個空流。與limit(n)互補 |
對映
方法 |
描述 |
map(Function f) |
接收一個函式作為引數,該函式會被應用到每個元素上,並將其對映成一個新的元素。 |
mapToDouble(ToDoubleFunction f) |
接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的DoubleStream。 |
mapToInt(ToIntFunction f) |
接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的IntStream。 |
mapToLong(ToLongFunction f) |
接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的LongStream。 |
flatMap(Function f) |
接受一個函式作為引數,將流中的每個值都換成另一個流,然後把所有流連線成一個流 |
排序
方法 |
描述 |
Sorted() |
產生一個新流,其中按自然順序排序 |
Sorted(Comparator comp) |
產生一個新流,其中按比較器順序排序 |
5. Stream 的終止操作
終端操作會從流的流水線生成結果。其結果可以是任何不是流的值,例如:List、Integer,甚至是void 。
查詢與匹配
方法 |
描述 |
allMatch(Predicate p) |
檢查是否匹配所有元素 |
anyMatch(Predicate p) |
檢查是否至少匹配一個元素 |
noneMatch(Predicatep) |
檢查是否沒有匹配所有元素 |
findFirst() |
返回第一個元素 |
findAny() |
返回當前流中的任意元素 |
count() |
返回流中元素總數 |
max(Comparatorc) |
返回流中最大值 |
min(Comparatorc) |
返回流中最小值 |
forEach(Consumerc) |
內部迭代(使用Collection 介面需要使用者去做迭代,稱為外部迭代。相反,Stream API 使用內部迭代——它幫你把迭代做了) |
規約
reduce(T iden, BinaryOperator b) |
可以將流中元素反覆結合起來,得到一個值。返回T |
reduce(BinaryOperator b) |
可以將流中元素反覆結合起來,得到一個值。返回Optional<T> |
收集
方法 |
描述 |
collect(Collector c) |
將流轉換為其他形式。接收一個Collector介面的實現,用於給Stream中元素做彙總的方法 |
Collector 介面中方法的實現決定了如何對流執行收集操作(如收集到List、Set、Map)。但是Collectors 實用類提供了很多靜態方法,可以方便地建立常見收集器例項,具體方法與例項如下表:
方法 |
返回型別 |
作用 |
|
toList |
List<T> |
把流中元素收集到List |
|
List<Employee>emps=list.stream().collect(Collectors.toList()); |
|||
toSet |
Set<T> |
把流中元素收集到Set |
|
Set<Employee>emps=list.stream().collect(Collectors.toSet()); |
|||
toCollection |
Collection<T> |
把流中元素收集到建立的集合 |
|
Collection<Employee>emps=list.stream().collect(Collectors.toCollection(ArrayList::new)); |
|||
counting |
Long |
計算流中元素的個數 |
|
longcount=list.stream().collect(Collectors.counting()); |
|||
summingInt |
Integer |
對流中元素的整數屬性求和 |
|
inttotal=list.stream().collect(Collectors.summingInt(Employee::getSalary)); |
|||
averagingInt |
Double |
計算流中元素Integer屬性的平均值 |
|
doubleavg=list.stream().collect(Collectors.averagingInt(Employee::getSalary)); |
|||
summarizingInt |
IntSummaryStatistics |
收集流中Integer屬性的統計值。如:平均值 |
|
IntSummaryStatisticsiss=list.stream().collect(Collectors.summarizingInt(Employee::getSalary)); |
|||
joining |
String |
連線流中每個字串 |
|
Stringstr=list.stream().map(Employee::getName).collect(Collectors.joining()); |
|||
maxBy |
Optional<T> |
根據比較器選擇最大值 |
|
Optional<Emp>max = list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary))) |
|||
minBy |
Optional<T> |
根據比較器選擇最小值 |
|
Optional<Emp>min=list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary))); |
|||
reducing |
歸約產生的型別 |
從一個作為累加器的初始值開始,利用BinaryOperator與流中元素逐個結合,從而歸約成單個值 |
|
inttotal=list.stream().collect(Collectors.reducing(0,Employee::getSalar,Integer::sum)); |
|||
collectingAndThen |
轉換函式返回的型別 |
包裹另一個收集器,對其結果轉換函式 |
|
inthow=list.stream().collect(Collectors.collectingAndThen(Collectors.toList(),List::size)); |
|||
groupingBy |
Map<K, List<T>> |
根據某屬性值對流分組,屬性為K,結果為V |
|
Map<Emp.Status, List<Emp>> map= list.stream() .collect(Collectors.groupingBy(Employee::getStatus)); |
|||
partitioningBy |
Map<Boolean,List<T>> |
根據true或false進行分割槽 |
|
Map<Boolean,List<Emp>>vd=list.stream().collect(Collectors.partitioningBy(Employee::getManage)); |