原文連接:http://www.javashuo.com/article/p-tlyrsuby-hz.htmljava
Stream類全路徑爲:java.util.stream.Stream
對Stream的描述,引用其餘文章中以爲比較好的介紹:編程
Java 8 中的 Stream 是對集合(Collection)對象功能的加強,它專一於對集合對象進行各類很是便利、高效的聚合操做(aggregate operation),或者大批量數據操做 (bulk data operation)。Stream API 藉助於一樣新出現的 Lambda 表達式,極大的提升編程效率和程序可讀性。
即Stream的原理:數組
這種風格將要處理的元素集合看做一種流, 流在管道中傳輸, 而且能夠在管道的節點上進行處理, 好比篩選, 排序,聚合等。元素流在管道中通過中間操做(intermediate operation)的處理,最後由最終操做(terminal operation)獲得前面處理的結果。
集合有兩種方式生成流:
- stream() − 爲集合建立串行流。
- parallelStream() − 爲集合建立並行流。併發
併發模式(parallelStream)可以充分利用多核處理器的優點,使用 fork/join 並行方式來拆分任務和加速處理過程。java中也提供了多種並行處理的方式,看到一片文章對各幾種並行的方式性能進行了測試,能夠參考下:java中幾種並行方式的性能分析。ide
Stream的的中間操做(intermediate)和最終操做(terminal)都包含哪些方法能夠從類結構中看到:
上面截圖基本包含了Strram的全部方法。函數
中間操做(intermediate)主要有如下方法(此類型的方法返回的都是Stream對象):
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered性能
終端操做(terminal)主要有如下方法:
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator測試
此處按照類結構(截圖)中的方法的順序(如下例子中使用了Lambda表達式及方法引用,不瞭解的請戳:Lambda介紹,方法引用),進行介紹:ui
filter:經過設置條件來過濾元素。
List<String> list = Arrays.asList("aaa","ddd","bbb","ccc","a2a","d2d","b2b","c2c","a3a","d3d","b3b","c3c");.net
list.stream()
.filter((s)->s.contains("a"))
.forEach(s -> System.out.println(s));
1
2
3
4
5
以上代碼使用filter方法過濾出只包含」a」的元素,而後經過forEach將知足條件的元素遍歷出來。輸出以下:
aaa
a2a
a3a
map:就是將對應的元素使用給定方法進行轉換。
list.stream()
.filter((s)->s.contains("a"))
.map((s)-> s + "---map")
.forEach(s -> System.out.println(s));
1
2
3
4
5
在filter的基礎上,給每一個元素後面添加字符串」—map」,輸出以下:
aaa—map
a2a—map
a3a—map
mapToInt:和map方法進行同樣的操做,可是轉換函數必須返回int類型
mapToLong:和map方法進行同樣的操做,可是轉換函數必須返回long類型
mapToDouble:和map方法進行同樣的操做,可是轉換函數必須返回double類型
此處以mapToInt進行演示:
list.stream()
.filter((s)->s.contains("a"))
.mapToInt((s)-> s.hashCode())
.forEach(s -> System.out.println(s));
1
2
3
4
在filter的基礎上,將每一個元素轉換爲其hashCode。輸出爲:
96321
94864
94895
flatMap:若是流的元素爲數組或者Collection,flatMap就是將每一個Object[]元素或Collection<Object>元素都轉換爲Object元素,以下:
Stream<String[]> 轉換爲 Stream<String>
Stream<Set> 轉換爲 Stream<String>
Stream<List> 轉換爲 Stream<String>
Stream<List> 轉換爲 Stream<Object>
看下例子:
List<String[]> setList = new ArrayList<>();
setList.add(new String[]{"aa","bb"});
setList.add(new String[]{"cc","dd"});
setList.add(new String[]{"ee","ff"});
//使用map方法
setList.stream()
.map(s->Arrays.stream(s))
.forEach(s-> System.out.println("map==" + s));
//使用flatMap方法
setList.stream()
.flatMap(s->Arrays.stream(s))
.forEach(s-> System.out.println("flatMap==" + s));
1
2
3
4
5
6
7
8
9
10
11
12
輸出以下:
map==java.util.stream.ReferencePipeline&Head@50040f0c
map==java.util.stream.ReferencePipeline&Head@2dda6444
map==java.util.stream.ReferencePipeline&Head@5e9f23b4
flatMap==aa
flatMap==bb
flatMap==cc
flatMap==dd
flatMap==ee
flatMap==ff
能夠看出map就是將數組流直接返回,flatMap是將數組流中的每一個元素都返回。flatMapToInt,flatMapToLong,flatMapToDouble相似,只不過返回的是對應的類型的流,此處不作演示。
distinct:將集合中的元素去重。
List<String> disList = Arrays.asList("aaa","ddd","bbb","ddd","aaa");
disList.stream()
.distinct()
.forEach(s-> System.out.println(s));
1
2
3
4
輸出以下:
aaa
ddd
bbb
sorted:將集合中的元素排序。
List<Integer> integerList = Arrays.asList(1,2,3,4);
integerList.stream()
.sorted()
.forEach(s-> System.out.println(s));
1
2
3
4
輸出以下:
1
2
3
4
能夠按照自定義排序:
integerList.stream()
.sorted((s1,s2)->s2.compareTo(s1))
.forEach(s-> System.out.println(s));
1
2
3
輸出以下:
4
3
2
1
peek:生成一個包含原Stream的全部元素的新Stream,同時會提供一個消費函數即引用的方法A,當Stream每一個元素被消費的時候都會先執行新Stream給定的方法A。peek是中間操做,若是pee後沒有最終操做,則peek不會執行。
integerList.stream()
.peek(s-> System.out.println("peek = "+s));
1
2
此時沒有輸出,代碼改成:
integerList.stream()
.peek(s-> System.out.println("peek = "+s))
.forEach(s-> System.out.println("forEach = "+s));
1
2
3
輸出以下:
peek = 1
forEach = 1
peek = 2
forEach = 2
peek = 3
forEach = 3
peek = 4
forEach = 4
limit:返回Stream的前n個元素。
integerList.stream()
.limit(1)
.forEach(s-> System.out.println(s));
1
2
3
輸出爲:
1
skip:刪除Stream的前n個元素。
integerList.stream()
.skip(1)
.forEach(s-> System.out.println(s));
1
2
3
輸出以下:
2
3
4
forEach:遍歷Stream中的每一個元素,前面每一個例子都有使用,此處再也不演示。
forEachOrdered:遍歷Stream中的每一個元素。
區別:
在串行流(stream)中沒有區別,在並行流(parallelStream)中若是數據源是有序集合,forEachOrdered輸出順序與數據源中順序一致,forEach則是亂序。
看下使用forEach:
integerList.stream()
.forEach(s-> System.out.println(s));
1
2
輸出(屢次測試,每次結果都不同):
3
1
4
2
再看使用forEachOrdered:
integerList.parallelStream()
.forEachOrdered(s-> System.out.println(s));
1
2
輸出(測試屢次,每次都是這個結果,與integerList中的元素順序一致):
2
1
3
4
toArray:將流轉換爲Object[]或者指定類型的數組。
Object[] array = integerList.stream().toArray();
String[] strArr = integerList.stream().toArray(String[]::new);
1
2
reduce:將集合中的每一個元素聚合成一條數據。有三種狀況:
reduce(BinaryOperator accumulator):此處須要一個參數,返回Optional對象:
Optional<Integer> reduce = integerList.stream().reduce((a, b) -> a + b);
1
reduce(T identity, BinaryOperator accumulator):此處須要兩個參數,第一個參數爲起始值,第二個參數爲引用的方法。從起始值開始,每一個元素執行一次引用的方法(方法引用的中的兩個參數:第一個參數爲上個元素執行方法引用的結果,第二個參數爲當前元素)。
int integer = integerList.stream().reduce(5,(a, b) -> a + b);
System.out.println(integer);
1
2
輸出爲:
15
此例中使用起始值爲5,對集合中每一個元素求和,能夠理解爲:5+2+1+3+4=15。
reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner):此處須要三個參數。此方法用在併發流(parallelStream)中,啓動多個子線程使用accumulator進行並行計算,最終使用combiner對子線程結果進行合併,返回identity類型的數據,看到有篇文章對這個解釋比較清楚:java8中3個參數的reduce方法怎麼理解?
collect:將流轉換成集合或聚合元素。有兩種狀況。接受一個參數和接受三個參數(三個參數在併發流parallelStream中使用),此處介紹一個參數的狀況,單個參數接受的參數類型爲Collector,Collectors 類實現了不少歸約操做,詳見:java8之collector
List<Integer> collects = integerList.stream()
.filter(a -> a > 1)
.collect(Collectors.toList());
System.out.println(collects);
1
2
3
4
此處統計集合中大於1的元素並最終返回list。輸出以下:
[2, 3, 4]
min:獲取集合中最小值。
Integer min = integerList.stream()
.filter(a -> a > 1)
.min((Integer a, Integer b) -> a.compareTo(b))
.get();
System.out.println(min);
1
2
3
4
5
輸出爲:
2
max:獲取集合中最大值。
Integer max = integerList.stream()
.filter(a -> a > 1)
.max((Integer a, Integer b) -> a.compareTo(b))
.get();
System.out.println(max);
1
2
3
4
5
輸出爲:
4
count:獲取集合中元素個數
long count = integerList.stream()
.filter(a -> a > 1)
.count();
System.out.println(count);
1
2
3
4
輸出爲:
3
anyMatch: Stream 中任意一個元素符合傳入的 predicate,返回 true
allMatch:Stream 中所有元素符合傳入的 predicate,返回 true
noneMatch:Stream 中沒有一個元素符合傳入的 predicate,返回 true
boolean b = integerList.stream()
.anyMatch(s -> s > 0);
boolean b1 = integerList.stream()
.allMatch(s -> s > 0);
boolean b2 = integerList.stream()
.noneMatch(s -> s > 0);
System.out.println("anyMatch = " + b);
System.out.println("allMatch = " + b1);
System.out.println("noneMatch = " + b2);
1
2
3
4
5
6
7
8
9
輸出:
anyMatch = true
allMatch = true
noneMatch = false
findFirst:若是數據源是有序集合,返回Stream 中第一個元素的Optional對象,若是是無序集合,則返回Stream 中任意一個元素的Optional對象。
Integer first = integerList.stream()
.findFirst()
.get();
System.out.println(first);
1
2
3
4
輸出爲:
2
findAny:返回Stream 中任意一個元素的Optional對象。
Integer any = integerList.stream()
.findAny()
.get();
System.out.println(any);
1
2
3
4
輸出爲:
2
Stream還有幾個靜態方法,返回都是Stream對象。
靜態方法以下:builder(返回Builder對象)、empty、of、iterate、generate、concat。
builder:返回一個Builder對象,Builder對象在調用build()返回Stream對象。
empty:返回一個空的有序的Stream對象。
of:返回包含單個元素的有序的Stream對象。
iterate:返回一個無限元素的有序的Stream對象。須要兩個參數,第一個參數爲初始值,第二個參數爲要引用的方法,而後會經過遞歸循環調用引用的方法。
Stream.iterate(2,s->s+s)
.limit(10)
.forEach(s-> System.out.println(s));
1
2
3
輸出爲:
2
4
8
16
32
64
128
256
512
1024
generate:返回一個無限元素的無序的的Stream對象。須要一個參數,參數爲引用的方法,而後會經過循環調用引用的方法來生成元素,經常使用於生成常量Stream和隨機元素Stream。
concat:將兩個Stream鏈接成一個Stream。須要兩個Stream做爲參數,若是兩個Stream都是有序的而且不管參數Stream是不是並行Stream,獲得的都是有序的Stream。輸出元素順序爲先輸出第一個Stream的元素,而後輸出第二個Stream的元素。當結果Stream關閉時候,兩個參數Stream同時關閉。
Stream.concat(integerList.stream(),disList.stream())
.forEach(s-> System.out.println(s));
1
2
輸出爲:
2 1 3 4 11 aaa ddd 33 bbb ddd aaa————————————————版權聲明:本文爲CSDN博主「暱稱2019」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。原文連接:https://blog.csdn.net/bluuusea/article/details/79967039