問題
本文重點是爲了介紹stream,但是在介紹之前我們可以先看一個問題
對於一個數組如何找出其中出現次數最多的數?
不用stream求解
public static void main(String[] args) {
Integer[] array = {12, 34, 44, 44, 33, 33, 33, 33};
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < array.length; i++) {
int key = array[i];
if (map.containsKey(key)) {
map.replace(key, map.get(key) + 1);
} else {
map.put(key, 1);
}
}
int key = array[0];
for (Entry<Integer, Integer> entry : map.entrySet()) {
if (entry.getValue() > map.get(key)) {
key = entry.getKey();
}
}
return key;
}
使用stream求解
public static void main(String[] args) {
Integer[] array = {12, 34, 44, 44, 33, 33, 33, 33};
Integer ss = Stream.of(array).collect(Collectors.groupingBy(Integer::valueOf))
.values()
.stream()
.sorted((a, b) -> b.size() - a.size())
.collect(Collectors.toList()).get(0).get(0);
System.out.println(ss);
}
肉眼可見,使用了stream後,對於數組,集合相關的一些聚合操作會顯得更加簡潔。對於上述兩種方案的性能在此不考慮。
stream概述
它作爲對原始集合操作的增強,在對集合,數組的集合操作上,通過配合lamda,提供了簡潔的編碼手段。它還提供串行和並行兩種方式,對於並行方式能利用如今多核心的優勢,加快運算,同時我們又不需要手動編寫多線程相關代碼。
stream不是一種數據結構,它與運算相關,在下面的參考文章中,把它比作高級的Iterator,我覺得有點道理。對於流裏的數據,是單向處理,一次性,處理過了就沒了。
從代碼上直觀感受,stream操作就是一連串的調用,符合我們對流的理解(這種鏈式調用有點像設計模式中的構造者模式,其它地方也比較常見)
stream能幹什麼
具體來講,我們對集合,數組進行過濾,映射,排序等這樣的操作時,可以考慮用stream
stream的核心概念
在使用stream的時候,我們一定要搞清楚的一個概念,流的操作分爲兩種
- Intermediate 在一個流處理中,可以有零個或多個,如filter,map等,需要注意的是,它是惰性執行的,比如,我使用了fiter和map,他不會先執行filter再執行map,它會將這兩種操作合併,然後在一次遍歷中完成。
Terminal:一個流只能有一個 terminal 操作,當這個操作執行後,流就被使用“光”了,無法再被操作。所以這必定是流的最後一個操作。Terminal 操作的執行,纔會真正開始流的遍歷,並且會生成一個結果,或者一個 side effect
如何獲取一個stream
簡單的介紹如何通過數組和集合獲取流
collection.stream(); // 集合獲取stream
Stream.of(array); // 數組獲取stream
使用案例
對數組進行排序
Integer[] array = {12, 34, 44, 44, 33, 33, 33, 33};
List<Integer> list = Arrays.stream(array).sorted((a, b) -> b-a).collect(Collectors.toList());
System.out.println(list);
當然stream能做的遠比這強大,它的intermeditate和terminal都分別提供了豐富的方法,有興趣的可以繼續閱讀如下參考文章