<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # Stream流 stream流是JDK1.8的另外一個新特性,前面已經介紹了《Lambda》和一些《常用函數式接口》,接下來的stream流將會把這兩個特性結合在一起,讓我們體會到其編寫代碼的簡潔之處。 正如前面所講到的lambda表達式體現的是一種**函數式編程思想**,更加關注于**做什么**,而不是**怎么做**。而stream流是一種流式操作, 和lambda表達式一起可以更加關注于**做什么**本身。 stream流和IO流中的流沒有任何關系,是兩個完全不同的概念。stream流的概念可以看成工廠中的流水線。在工廠的流水線生產中,每一步中它都要對源材料進行操作,最后得到想要的產品。stream流也是類似的,每一步它將對源數據進行操作(過濾模式),最后得出符合條件的數據。 因此,stream流主要是用在集合的聚合操作中,使用它可以大大簡化了集合的過濾數據的操作。就跟我們使用SQL語句查詢數據中的數據一樣,我們只是關注了查了哪些數據本身,而底層究竟是怎么查是由數據庫系統幫我們實現好的,stream流也是類似的。 &nbsp; ## 集合遍歷操作舉例 ### 復雜的操作 集合做為java中最常用的框架,我們在程序中或多或少都要用到它,其中最常見的應該就要屬遍歷操作了。在以前的遍歷集合的操作中,最常見的就是for迭代器循環和增強for循環了。例如下面使用foreach篩選出字符串數組中長度大于4,包含a的數據。 ```java import java.util.ArrayList; import java.util.List; public class StreamDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("python"); list.add("java"); list.add("javascript"); List<String> list1 = new ArrayList<>(); //創建一個新列表,保存長度大于4的數據 for (String str : list) { if (str.length() > 4) { list1.add(str); } } // list1=["python", "javascript"] List<String> list2 = new ArrayList<>(); //創建一個新列表,保存含有a的數據 for(String str : list1) { if (str.contains("a")) { list2.add(str); } } for (String str : list2) { //最后遍歷數據 System.out.println(str); } // javascript } } ``` 從上面的例子可以看出,為了達到想要的操作,竟然使用了3個循環,并且還額外增加了2個臨時的列表來保存數據,3個for循環也有點冗余了,這里這么寫只是為了體現出每步的步驟,與stream流的方式進行對比。 其實我們想一想就可以發現,for循環這個語法好像不是必要的,它更像一個工具,告訴我們怎么做,但是其實我們想要僅僅只是做**取出長度大于4并且含有a的數據這件事罷了**。下面我們來看stream流API是怎么關注于“做什么”本身的。 ### 簡潔的操作 ```java import java.util.ArrayList; import java.util.List; public class StreamDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("python"); list.add("java"); list.add("javascript"); list.stream() .filter(s -> s.length() > 4) //過濾長度大于4的數據 .filter(s -> s.contains("a")) //過濾有a的數據 .forEach(s -> System.out.println(s)); //打印數據,這里更加推薦的是使用方法引用的方式 System.out::println } } ``` 可以發現,用API操作很直接明了,filter用來過濾數據,forEach用來遍歷數據,而不用在寫for循環和if條件的判斷了。至于里面究竟是怎么實現的,在應用層面上,我們并不用太過于關心。 &nbsp; ## stream流思想 stream流不是任何一種數據類型,它并不會存儲數據,本身也不是數據(與IO流沒關系),它更像是一種函數模型,在這個模型方案中體現了該函數對數據做了哪些操作。如圖: :-: ![stream流模型](https://img-blog.csdnimg.cn/20200906214911463.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDE4NDk5MA==,size_16,color_FFFFFF,t_70#pic_center) 圖中通過filter,map,skip等操作(后面會講這些操作的具體使用方式)將集合數據進行一步步的操作,值得注意的是,這些操作并沒有被真正的執行,只有在最后一步進行count操作的時候,才會真正的執行前面的函數對集合進行操作,并且它是不會操作到集合本身的內容的。這種特性得益于lambda的延遲執行特性。例如上面的例子再遍歷一次list集合: :-: ![stream流不會改變原集合內容](https://img-blog.csdnimg.cn/2020090621494578.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDE4NDk5MA==,size_16,color_FFFFFF,t_70#pic_center) &nbsp; ### 相關概念 流的基礎特征: - Pipelining:管道,即每一次中間執行的操作都會返回一個流對象,例如filter方法返回值仍然是一個流對像,這樣就可以在每個方法之后形成鏈式調用,就像管道一樣連接起來。 - 內部迭代:以前使用for循環時進行的是在集合外部進行迭代的(程序由我們自己編寫),這稱為外部迭代,而stream是通過自身提供的內部迭代方法進行數據的遍歷(迭代方式不可見) - 元素類型單一:stream流中的元素類型的是單一的,不能操作例如map這種鍵值對的元素。 常用方法分類: - **延遲方法**:指的是這類方法會返回一個stream流對象,例如filter,map。因為返回的是一個stream流對象,因此這些方法支持鏈式調用,但是就跟前面講到的那樣,這些方法并不會真正執行,只是提供了一個調用鏈模型。只有當執行終結方法時這些方法才會真正的被執行 - **終結方法**:指的是這類方法的返回值不再是stream流對象,因此不能在使用鏈式調用的方法繼續調用下去,管道連接將在這里停止,一旦調用這類方法,前面的函數模型也會真正的被執行。這類方法有**count**和**forEach**。同時,一旦調用了這類方法,之后在調用該stream流對象的方法就會報錯。 &nbsp; ## 獲取stream流對象的方式 - 通過Collection集合對象獲取。 - Stream接口中有個靜態方法of可以獲取數組對應的流對象。 ### Collection集合對象獲取 &nbsp;&nbsp;在Collection接口中加入了默認的stream()方法用來獲取流對象,因此其實現類都能通過該方法獲取流對象 ```java default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } ``` 例如: ```java public class StreamDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); Stream<String> stream1 = list.stream(); Set<String> set = new HashSet<>(); Stream<String> stream2 = set.stream(); Vector<String> vector = new Vector<>(); Stream<String> stream3 = vector.stream(); //...Collection實現類及其子類均可獲得 } } ``` &nbsp;&nbsp; 但是由于Map集合并不是Collection接口的實現類,因此不能通過調用stream()方法來獲取流對象,這里是因為Map集合是鍵值對的形式存在的,不能符合流元素的單一特征。但是可以獲取其鍵,值對應的流對象。例如 ```java public class StreamDemo { public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); Stream<String> keyStream = map.keySet().stream(); //獲取鍵的流對象 Stream<Integer> valueStream = map.values().stream(); //獲取值的流對象 Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream(); //獲取Entry類型的流對象 } } ``` &nbsp; ### 靜態方法獲取 &nbsp;&nbsp;stream接口中有兩個of靜態方法,用來獲取單個數組的流對象或者數組的流對象 ```java public static<T> Stream<T> of(T t) { return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false); } public static<T> Stream<T> of(T... values) { //可變參數,也可以傳遞一個數組 return Arrays.stream(values); } ``` 例如: ```java public class StreamMapDemo { public static void main(String[] args) { Stream<String> stream1 = Stream.of("6", "8", "10"); //傳遞不固定的參數 Stream<String> stream2 = Stream.of("6"); } } ``` &nbsp; ## 常用方法概述 ### filter ```java Stream<T> filter(Predicate<? super T> predicate); ``` &nbsp;&nbsp;使用Predicate函數式接口中的test方法來過濾數據,test方法用來判斷參數T是否判斷條件,符合條件的話返回true,否則返回false,在這里配合filter使用的話即如果test返回false,則過濾該數據。例如上面使用的: ```java list.stream().filter(s -> s.length() > 4); ``` &nbsp;&nbsp;即當元素的長度大于4時,Predicate接口的test方法返回true,則不用過濾該數據。是一個**延遲方法**。 &nbsp; ### map ```java Stream<R> map(Function<? super T, ? extends R> mapper); ``` &nbsp;&nbsp;使用Function函數式接口的apply方法,將T類型轉化R類型數據返回,即將T映射成R。例如,將字符串數字數組轉化為Integer數組 ```java public class StreamMapDemo { public static void main(String[] args) { Stream<String> original = Stream.of("6", "8", "10"); Stream<Integer> result = original.map(str‐>Integer.parseInt(str)); //String 類型轉化為Integer類型 } } ``` 是一個**延遲方法**。 &nbsp; ### limit ```java Stream<T> limit(long maxSize); ``` &nbsp;&nbsp;用來截取流元素的前maxSize個數據,如果maxSize大于集合的長度,則不用截取。是一個**延遲方法**。 &nbsp; ### skip ```java Stream<T> skip(long n); ``` &nbsp;&nbsp;與limit相反的是,skip是用來跳過前面的n個元素,如果n大于流元素集合的長度,則會得到一個元素為0的空流。是一個**延遲方法**。 &nbsp; ### concat ```java public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {} ``` &nbsp;&nbsp;如果希望合并兩個流對象的話,可以使用Stream接口的靜態方法concat,用來將兩個流a,b 合并成一個新的stream流并返回。 &nbsp; ### forEach ```java void forEach(Consumer<? super T> action); ``` &nbsp;&nbsp;由方法定義可以方法,該方法使用了Consumer接口,該接口用來消費數據,對數據進行處理的,用來對流的每個元素執行此操作。是一個**終結方法**。 &nbsp; ### count ```java long count(); ``` &nbsp;&nbsp;與Collection集合中的size一樣,用于統計stream元素的個數(當然這里stream流并不是容器);是一個終結方法。 &nbsp; > 備注:其實stream流中的方法究竟是延遲方法還是終結方法,主要看其返回值是否是一個流對象即可,是的話就是延遲方法,否則就是終結方法。 &nbsp; ## 小結 1. stream流概念并不同于IO流,它是lambda表達式函數式編程思想的衍生物。 2. 使用stream流可以大大簡化我們對Collection集合的操作,并且Collection集合提供了獲取該對象的stream的方法。 3. stream流的延遲方法(可以看返回值區分)并不會真正執行,只有到調用終結方法時才會將該stream流對象按照所連接的管道順序執行。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看