Java新特性之Stream流
什麼是Stream流
java.util.stream.*
是Java 8引入的函數語言程式設計類庫,以一種宣告的方式來處理元素集合裡的資料,可以理解為shell
指令碼中管道
(|
)一樣的概念。
首先將資料來源
(集合
,陣列
,I/O channel
,產生器generator
)的元素
形成佇列
,然後管道中傳輸,並且可以在管道的節點
上進行
聚合操作
, 比如篩選
,排序
,聚合
,計算
等,這個視為中間操作
。最終操作
將結果返回。Java中將這一系列操作抽象為Stream流
。
Stream流的分類
- stream() :序列流
- parallelStream() :並行流
PS:序列流與並行流的區別就是單執行緒與多執行緒的區別,並行流處理比序列流快很多。具體業務使用具體流,比如並行流對元素的排序(sorted() )就返回了錯誤的結果,對條件判斷(filter() )則不影響結果。
Stream流的特徵
- Pipelining :中間操作都會返回流物件本身, 如同流式風格(fluent style)的管道。 可以進行延遲執行(laziness)和短路( short-circuiting)等操作。
- 內部迭代 : 通常集合遍歷都是通過Iterator或者For-Each的方式, 顯式的在集合外部進行外部迭代。 Stream提供了內部迭代的方式, 通過訪問者模式(Visitor)實現。
為什麼要Stream流
為了讓開發者能夠快速,簡潔,高效地對資料來源
(集合
,陣列
,I/O channel
,產生器generator
)中的元素進行操作。
凡是提供了stream()
方法的集合都可以用流處理。如Collection
介面。
如何使用Stream流
介面說明
java.util.stream.* 介面說明
介面 | 說明 |
---|---|
BaseStream <T,S extendsBaseStream <T,S» | 流的基本介面,它是支援序列和並行聚合操作的元素序列。 |
Collector <T,A,R> | 可變縮減操作,將輸入元素累積到可變結果容器中,可選地在處理完所有輸入元素後將累積結果轉換為最終表示。 |
DoubleStream | 一系列原始雙值元素,支援序列和並行聚合操作。 |
DoubleStream.Builder |
DoubleStream
的可變構建器。 |
IntStream | 支援序列和並行聚合操作的一系列原始int值元素。 |
IntStream.Builder |
IntStream
的可變構建器。 |
LongStream | 一系列原始長值元素,支援序列和並行聚合操作。 |
LongStream.Builder |
LongStream
的可變構建器。 |
Stream
|
支援序列和並行聚合操作的一系列元素。 |
Stream.Builder
|
Stream
的可變構建器。 |
Stream的方法說明
java.util.stream.Stream 類的方法說明
返回值型別 | 方法 | 說明 |
---|---|---|
boolean
|
allMatch(Predicate<? super T> predicate)
|
返回此流的所有元素是否與提供的謂詞匹配。 |
boolean
|
anyMatch(Predicate<? super T> predicate)
|
返回此流的任何元素是否與提供的謂詞匹配。 |
static <T> Stream.Builder<T>
|
builder()
|
返回Stream的構建器。 |
<R,A> R
|
collect(Collector<? super T,A,R> collector)
|
使用收集器對此流的元素執行可變減少操作。 |
<R> R
|
collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)
|
Performs amutable reduction operation on the elements of this stream. |
static <T> Stream<T>
|
concat(Stream<? extends T> a, Stream<? extends T> b)
|
建立一個延遲連線的流,其元素是第一個流的所有元素,後跟第二個流的所有元素。 |
long
|
count()
|
返回此流中元素的數量。 |
Stream<T>
|
distinct()
|
返回由此流的不同元素(根據Object.equals(Object))組成的流。 |
static <T> Stream<T>
|
empty()
|
返回一個空的順序Stream。 |
Stream<T>
|
filter(Predicate<? super T> predicate)
|
返回由與此給定謂詞匹配的此流的元素組成的流。 |
Optional<T>
|
findAny()
|
返回描述流的某個元素的Optional,如果流為空,則返回空Optional。 |
Optional<T>
|
findFirst()
|
返回描述此流的第一個元素的Optional,如果流為空,則返回空Optional。 |
<R> Stream<R>
|
flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
|
返回一個流,該流包含將此流的每個元素替換為通過將提供的對映函式應用於每個元素而生成的對映流的內容的結果。 |
DoubleStream
|
flatMapToDouble(Function<? super T,? extends DoubleStream> mapper)
|
返回一個DoubleStream,它包含將此流的每個元素替換為通過將提供的對映函式應用於每個元素而生成的對映流的內容的結果。 |
IntStream
|
flatMapToInt(Function<? super T,? extends IntStream> mapper)
|
返回一個IntStream,它包含將此流的每個元素替換為通過將提供的對映函式應用於每個元素而生成的對映流的內容的結果。 |
LongStream
|
flatMapToLong(Function<? super T,? extends LongStream> mapper)
|
返回一個LongStream,它包含將此流的每個元素替換為通過將提供的對映函式應用於每個元素而生成的對映流的內容的結果。 |
void
|
forEach(Consumer<? super T> action)
|
對此流的每個元素執行操作。 |
void
|
forEachOrdered(Consumer<? super T> action)
|
如果流具有已定義的遭遇順序,則按流的遭遇順序對此流的每個元素執行操作。 |
static <T> Stream<T>
|
generate(Supplier<T> s)
|
返回無限順序無序流,其中每個元素由提供的Supplier生成。 |
static <T> Stream<T>
|
iterate(T seed, UnaryOperator<T> f)
|
返回通過將函式f迭代應用於初始元素種子而生成的無限順序有序流,生成由種子,f(seed),f(f(seed))等組成的流。 |
Stream<T>
|
limit(long maxSize)
|
返回由此流的元素組成的流,截斷長度不超過maxSize。 |
<R> Stream<R>
|
map(Function<? super T,? extends R> mapper)
|
返回一個流,該流包含將給定函式應用於此流的元素的結果。 |
DoubleStream
|
mapToDouble(ToDoubleFunction<? super T> mapper)
|
返回DoubleStream,其中包含將給定函式應用於此流的元素的結果。 |
IntStream
|
mapToInt(ToIntFunction<? super T> mapper)
|
返回一個IntStream,它包含將給定函式應用於此流的元素的結果。 |
LongStream
|
mapToLong(ToLongFunction<? super T> mapper)
Returns aLongStream
consisting of the results of applying the given function to the elements of this stream. |
返回一個LongStream,它包含將給定函式應用於此流的元素的結果。 |
Optional<T>
|
max(Comparator<? super T> comparator)
|
根據提供的Comparator返回此流的最大元素。 |
Optional<T>
|
min(Comparator<? super T> comparator)
|
根據提供的Comparator返回此流的最小元素。 |
boolean
|
noneMatch(Predicate<? super T> predicate)
|
返回此流的元素是否與提供的謂詞匹配。 |
static <T> Stream<T>
|
of(T... values)
|
返回其元素為指定值的順序有序流。 |
static <T> Stream<T>
|
of(T t)
|
返回包含單個元素的順序Stream。 |
Stream<T>
|
peek(Consumer<? super T> action)
|
返回由此流的元素組成的流,此外還在從結果流中消耗元素時對每個元素執行提供的操作。 |
Optional<T>
|
reduce(BinaryOperator<T> accumulator)
|
使用關聯累加函式執行此流的元素的減少,並返回描述減少值的Optional(如果有)。 |
T
|
reduce(T identity, BinaryOperator<T> accumulator)
|
使用提供的標識值和關聯累加函式執行此流的元素的減少,並返回減少的值。 |
<U> U
|
reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
|
使用提供的標識,累積和組合功能,對此流的元素執行減少。 |
Stream<T>
|
skip(long n)
|
在丟棄流的前n個元素後,返回由此流的其餘元素組成的流。 |
Stream<T>
|
sorted()
|
返回由此流的元素組成的流,按照自然順序排序。 |
Stream<T>
|
sorted(Comparator<? super T> comparator)
|
返回由此流的元素組成的流,根據提供的Comparator進行排序。 |
Object[]
|
toArray()
|
返回包含此流的元素的陣列。 |
<A> A[]
|
toArray(IntFunction<A[]> generator)
|
返回一個包含此流元素的陣列,使用提供的生成器函式分配返回的陣列,以及分割槽執行或調整大小可能需要的任何其他陣列。 |
例項
People.java
public class People { private String name; private int age; private String address; public People(String name,int age,String address) { this.name = name; this.age = age; this.address = address; }; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "People [name=" + name + ", age=" + age + ", address=" + address + "]"; } }
Test.java
import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; public class Test10 { public static void main(String[] args) { Collection< People > peoples = Arrays.asList( new People( "a",1,"aa" ), new People( "b",2,"bb" ), new People( "c",3,"cc" ), new People( "d",4,"dd" ), new People( "e",5,"ee" ), new People( "f",6,"ff" ), new People( "g",7,"gg" ), new People( "h",8,"hh" ), new People( "i",9,"ii" ) ); System.out.print("\n使用iterator\n"); // 使用iterator for (Iterator iterator = peoples.iterator(); iterator.hasNext();) { People people = (People) iterator.next(); System.out.println(people.toString()); } System.out.print("\n使用lambda\n"); // 使用lambda peoples.forEach(people -> { System.out.println(people.toString()); }); System.out.print("\n使用方法引用\n"); // 使用方法引用 peoples.forEach(System.out::println); System.out.print("\n使用Stream流limit()方法\n"); // Stream提供了 forEach()方法來迭代(Iteration)流中的每個資料 // Stream提供了limit()方法用於獲取指定數量的流。 peoples.stream().limit(8).forEach(s -> { System.out.println(s.toString()); }); System.out.print("\n使用Stream流map()方法\n"); // Stream提供了map()方法用於對映每個元素到對應的結果 peoples.stream().map(people -> { if (people.getAge() == 5) { people.setAge(0); } return people; }).forEach(System.out::println); System.out.print("\n使用Stream流filter()方法\n"); // Stream提供了filter()方法用於通過設定的條件過濾出元素。 // parallelStream提供了count()方法用於統計符合條件的元素的數量 long a = peoples.parallelStream().filter(people -> { if (people.getAge() == 0 || people.getName().equals("a")) { return true; } return false; }).count(); System.out.println("符合條件的總共:" + a); // Stream提供了sorted()方法用於對元素進行排序 System.out.print("\n使用Stream流sorted()方法\n"); peoples.stream().sorted(Comparator.comparing(People::getAge).reversed()).forEach(System.out::println); } }
輸出結果
使用iterator People [name=a, age=1, address=aa] People [name=b, age=2, address=bb] People [name=c, age=3, address=cc] People [name=d, age=4, address=dd] People [name=e, age=5, address=ee] People [name=f, age=6, address=ff] People [name=g, age=7, address=gg] People [name=h, age=8, address=hh] People [name=i, age=9, address=ii] 使用lambda People [name=a, age=1, address=aa] People [name=b, age=2, address=bb] People [name=c, age=3, address=cc] People [name=d, age=4, address=dd] People [name=e, age=5, address=ee] People [name=f, age=6, address=ff] People [name=g, age=7, address=gg] People [name=h, age=8, address=hh] People [name=i, age=9, address=ii] 使用方法引用 People [name=a, age=1, address=aa] People [name=b, age=2, address=bb] People [name=c, age=3, address=cc] People [name=d, age=4, address=dd] People [name=e, age=5, address=ee] People [name=f, age=6, address=ff] People [name=g, age=7, address=gg] People [name=h, age=8, address=hh] People [name=i, age=9, address=ii] 使用Stream流limit()方法 People [name=a, age=1, address=aa] People [name=b, age=2, address=bb] People [name=c, age=3, address=cc] People [name=d, age=4, address=dd] People [name=e, age=5, address=ee] People [name=f, age=6, address=ff] People [name=g, age=7, address=gg] People [name=h, age=8, address=hh] 使用Stream流map()方法 People [name=a, age=1, address=aa] People [name=b, age=2, address=bb] People [name=c, age=3, address=cc] People [name=d, age=4, address=dd] People [name=e, age=0, address=ee] People [name=f, age=6, address=ff] People [name=g, age=7, address=gg] People [name=h, age=8, address=hh] People [name=i, age=9, address=ii] 使用Stream流filter()方法 符合條件的總共:2 使用Stream流sorted()方法 People [name=i, age=9, address=ii] People [name=h, age=8, address=hh] People [name=g, age=7, address=gg] People [name=f, age=6, address=ff] People [name=d, age=4, address=dd] People [name=c, age=3, address=cc] People [name=b, age=2, address=bb] People [name=a, age=1, address=aa] People [name=e, age=0, address=ee]