只有光頭才能變強。java
文本已收錄至個人GitHub倉庫,歡迎Star:github.com/ZhongFuChen…git
上一篇講解到了Lambda表達式的使用《最近學到的Lambda表達式基礎知識》,還沒看的同窗能夠先去閱讀一下哈~github
相信也有很多的同窗想要知道:Lambda表達式在工做中哪一個場景會用得比較多?跟Lambda搭邊的,使用Stream流會比較多編程
通常人第一次看Stream流的代碼,都會有點看不懂(它的代碼看起來好像就不是寫Java同樣.),但願這篇文章能帶你們入個門數組
你們在自學時,大多數會學過一個程序:算出從數組元素的和
,當時咱們是怎麼寫的?通常來講是這樣的:併發
public static void main(String[] args) {
int[] nums = { 1, 2, 3 };
int sum = 0;
for (int i : nums) {
sum += i;
}
System.out.println("結果爲:" + sum);
}
複製代碼
若是咱們使用Stream流的話,能夠這樣:dom
public static void main(String[] args) {
int[] nums = { 1, 2, 3 };
int sum2 = IntStream.of(nums).sum();
System.out.println("結果爲:" + sum2);
}
複製代碼
從代碼量上能夠明顯看出,用Stream流的方式會少一些。性能
我理解的Stream流編程就是:某些場景會常常用到操做(求和/去重/過濾....等等),已經封裝好API給你了,你本身別寫了,調我給你提供的API就行了。測試
回到咱們最原始的代碼:優化
public static void main(String[] args) {
int[] nums = { 1, 2, 3 };
int sum = 0;
for (int i : nums) {
sum += i;
}
System.out.println("結果爲:" + sum);
}
複製代碼
若是咱們想要for
循環的內部支持併發的話,顯然不太好去寫。但使用Stream流的方式,調用一個方法就能夠支持併發(parallel):
public static void main(String[] args) {
int[] nums = { 1, 2, 3 };
int sum2 = IntStream.of(nums).parallel().sum();
System.out.println("結果爲:" + sum2);
}
複製代碼
優勢:調API確定是比本身寫的代碼量要少。
缺點:不太方便調試
爲何要使用Stream流在我看來就是以上兩個緣由:
使用Stream流分爲三步:
建立流咱們最經常使用的就是從集合中建立出流
/** * 返回的都是流對象 * @param args */
public static void main(String[] args) {
List<String> list = new ArrayList<>();
// 從集合建立
Stream<String> stream = list.stream();
Stream<String> stream1 = list.parallelStream();
// 從數組建立
IntStream stream2 = Arrays.stream(new int[]{2, 3, 5});
// 建立數字流
IntStream intStream = IntStream.of(1, 2, 3);
// 使用random建立
IntStream limit = new Random().ints().limit(10);
}
複製代碼
怎麼理解中間操做?意思是這樣的:在上面咱們已經能建立出Stream了,咱們是對Stream進行操做,對Stream操做返回完返回的仍是Stream,那麼咱們稱這個操做爲中間操做。
好比,咱們如今有個字符串my name is 007
,代碼以下:
String str = "my name is 007";
Stream.of(str.split(" ")).filter(s -> s.length() > 2)
.map(s -> s.length()).forEach(System.out::println);
複製代碼
分解:
一、從字符串數組建立出流對象:
Stream<String> split = Stream.of(str.split(" "));
複製代碼
二、經過流對象的API執行中間操做(filter),返回的仍是流對象:
Stream<String> filterStream = split.filter(s -> s.length() > 2);
複製代碼
三、經過返回的流對象再執行中間操做(map),返回的仍是流對象:
Stream<Integer> integerStream = filterStream.map(s -> s.length());
複製代碼
由於中間操做返回的都是流對象,因此咱們能夠鏈式調用。
注意:Stream上的操做並不會當即執行,只有等到用戶真正須要結果的時候纔會執行(惰性求值)。
好比說,peek()
是一箇中間操做,返回的是Stream流對象,只要它不執行最終的操做,這個Stream是不會執行的。
String str = "my name is 007";
Stream.of(str.split(" ")).peek(System.out::println); // 不會有信息打印
複製代碼
最終操做返回的再也不是Stream對象,調用了最終操做的方法,Stream纔會執行。仍是以上面的例子爲例:
String str = "my name is 007";
Stream.of(str.split(" ")).peek(System.out::println).forEach(System.out::println)
複製代碼
此次咱們加入了最終操做,因此此次的Stream流會被執行,因爲中間操做和最終操做都是執行打印,因此會看到兩次打印:
至於中間操做和最終操做怎麼區分,咱們以返回值來看就好了。中間操做返回的是Stream實例對象,最終操做返回的不是Stream實例對象:
這篇文章主要跟你們一塊兒初步認識一下Stream流,至於中間操做、最終操做的API講解我就不寫了(網上的教程也不少)
使用Stream的緣由我認爲有兩個:
for
性能不比Stream API 差多少參考資料:
樂於輸出乾貨的Java技術公衆號:Java3y。公衆號內有200多篇原創技術文章、海量視頻資源、精美腦圖,關注便可獲取!
以爲個人文章寫得不錯,點贊!