一直在寫中間件相關的代碼,提供SDK給業務方使用,但不少業務方還一直停留在1.7版本,遲遲不升級,爲了兼容性,不敢在代碼中使用Java8的一些新特性,好比Stream之類的,雖然不能用,但仍是要學一下。java
Stream 是Java 8中添加的一個新特性,它與 java.io 包裏的 InputStream 和 OutputStream 是徹底不一樣的概念。它藉助於 Lambda 表達式,可讓你以一種聲明的方式處理數據,能夠極大提升Java程序員的生產力,讓程序員寫出高效率、乾淨、簡潔的代碼。程序員
直接上Demo,感覺一下安全
List<String> myList = Arrays.asList("a", "b", "c", "d", "e");
數據結構
myList.stream()
dom
.filter(s -> s.startsWith("1"))
函數
.map(String::toUpperCase)
工具
.sorted()
code
.forEach(System.out::println);
中間件
當使用一個流的時候,一般包括三個基本步驟:對象
獲取一個數據源(source)
數據轉換
執行操做獲取想要的結果
每次轉換原有 Stream 對象不改變,返回一個新的 Stream 對象(能夠有屢次轉換),這就容許對其操做能夠像鏈條同樣排列,變成一個管道,以下圖所示。
在Stream中,分爲兩種操做
中間操做
結束操做
中間操做返回Stream,終端操做返回void或者非Stream結果,在demo中, filter
、 map
、 sorted
都算是中間操做,而 forEach
是一個結束操做。
建立Stream的方式不少,最多見的是從Collections,List 和 Set中生成
List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");
Stream<String> stream = myList.stream()
在對象myList上調用方法 stream() 返回一個常規對象Stream。
也能夠從一堆已知對象中生成。
Stream<String> stream = Stream.of("a1", "a2", "a3")
固然了,還有其它方式:
Collection.stream()
Collection.parallelStream()
BufferedReader.lines()
Files.walk()
BitSet.stream()
Random.ints()
JarFile.stream()
....
forEach
方法接收一個 Lambda 表達式,用來迭代流中的每一個數據
Stream.of(1, 2, 3).forEach(System.out::println);
// 1
// 2
// 3
map
用於映射每一個元素到對應的結果
Stream.of(1, 2, 3).map( i -> i*i).forEach(System.out::println);
// 1
// 4
// 9
filter
用於經過設置的條件過濾出元素
Stream.of(1, 2, 3).filter( i -> i == 1).forEach(System.out::println);
// 1
limit
用於用於獲取指定數量的流
Stream.of(1, 2, 3, 4, 5).limit(2).forEach(System.out::println);
// 1
// 2
sorted
用於對流進行排序
Stream.of(4, 1, 5).sorted().forEach(System.out::println);
// 1
// 4
// 5
有三個 match 方法,從語義上說:
allMatch:Stream 中所有元素符合傳入的 predicate,返回 true
anyMatch:Stream 中只要有一個元素符合傳入的 predicate,返回 true
noneMatch:Stream 中沒有一個元素符合傳入的 predicate,返回 true
它們都不是要遍歷所有元素才能返回結果。例如 allMatch 只要一個元素不知足條件,就 skip 剩下的全部元素,返回 false。
boolean result = Stream.of("a1", "a2", "a3").allMatch(i -> i.startsWith("a"));
System.out.println(result);
// true
reduce
方法根據指定的函數將元素序列累積到某個值。此方法有兩個參數:
起始值
累加器函數。
若是有一個List,但願獲得全部這些元素和一些初始值的總和。
int result = Stream.of(1, 2, 3).reduce(20, (a,b) -> a + b);
System.out.println(result);
// 26
Collectors類中提供了功能豐富的工具方法
toList
toSet
toCollection
toMap
...
而這些方法,都須要經過 collect
方法傳入。
Set<Integer> result = Stream.of(1, 1, 2, 3).collect(Collectors.toSet());
System.out.println(result);
// [1, 2, 3]
collect
能夠把Stream數據流轉化爲Collection對象,
除了常規的對象Stream,還有一些有特殊類型的Stream,用於處理基本數據類型int、long和double,它是IntStream、LongStream和DoubleStream。
好比可使用IntStream.range()來代替常規的for循環。
IntStream.range(1, 4).forEach(System.out::println);
Random的ints方法能夠返回一個隨機數據流,好比返回1到100的10個隨機數。
Random random = new Random();
random.ints(1, 100).limit(10).forEach(System.out::println);
List<String> output = wordList.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
總之,Stream 的特性能夠概括爲:
Stream並非一種數據結構,它只是某種數據源的一個視圖
對Stream的任何修改都不會修改背後的數據源,好比對stream執行過濾操做並不會刪除被過濾的元素,而是會產生一個不包含被過濾元素的新Stream。
Stream上的操做並不會當即執行,只有等到用戶真正須要結果的時候纔會執行。
Stream只能被「消費」一次,一旦遍歷過就會失效,就像容器的迭代器那樣,想要再次遍歷必須從新生成。
全部 Stream 的操做必須以 lambda 表達式爲參數