Java高階特性1_流庫_初體驗

隨遇丿而安發表於2020-10-07

Java高階特性流庫_初體驗

面對結果程式設計

在程式設計裡, 有兩種程式設計方式, 一種是面對過程程式設計, 一種是面對結果程式設計. 兩者區別如下

程式導向程式設計

程式導向程式設計

程式導向程式設計需要程式設計程式讓程式依次執行得到自己想要的結構

面向結果程式設計

流庫帶給我們的好處就是我們不需要知道過程, 只需要提供我們的需要, 具體怎麼做由流庫內部實現

1. 迭代到流程式碼演示

流庫正如其名所示, 它處理的是大量元素.

這裡可以將流庫比作一個水管, 流庫中的許多函式比作水龍頭, 函式成立, 水龍頭便開啟讓水流動, 函式不成立, 水龍頭關閉, 鎖住水.

public class FlowDemo2 {
    public static void main(String[] args) throws IOException {
        int count = 0;
//        讀取文字檔案, 其中是一段文章
        String s = new String(Files.readAllBytes(Paths.get("src","a.txt")));
        String[] split = s.split("\\n");
//        程式導向程式設計 統計段落長度大於90的數量
        for (String s1 : split){
            if(s1.length() > 90) count++;
        }
        
//        面向結果程式設計 統計段落長度大於90的數量
        List<String> list = Arrays.asList(split);
        System.out.println(list.stream().filter(w -> w.length() > 90).count());
        
//        另一種陣列轉流的方式
//        Stream<String> stream = Arrays.stream(split);
//        System.out.println(stream);
//        System.out.println(stream.filter(w -> w.length() > 90)
//                .count());
//        System.out.println(count);
    }
}

結果一致, 都為6.

2. 流的優點

  1. 更加簡潔明瞭
  2. 能夠鏈式操作( 每次返回的資料型別都是流 )
  3. 流不會儲存元素, 節約記憶體
  4. 流的操作不會修改資料來源
  5. 我的理解: 流是單向的, 只會單方向流動改變, 不會改變之前的狀態, 流動過了就過了, 不會再回來

3. 建立流的方式

根據流的長度可以分為無限流和有限長度的流

Java中有大量API可以產生流, 假如有方法可以返回大量資料, 那麼就可以查查文件看, 是否有轉換為流的方法.

Stream介面生成有限長度的流的方式

//        第一種
//        Stream.of(可變長引數陣列)
        int[] arr1 = {2, 34, 6, 8, 9, 19};
        int[] arr2 = {2, 4, 5};
        Stream<int[]> stream1 = Stream.of(arr1, arr2);
        System.out.println(stream1.getClass());

//        第二種
        int[] arr3 = {2, 34, 6, 8, 9, 19};
//        擷取陣列部分, 從1到2, 不包括結束
        IntStream stream = Arrays.stream(arr3, 1, 3);
        System.out.println(stream.sum());

//		  建立空流
		Stream.empty()

Stream介面生成無限流的方法

//        第三種, 建立無限流之generate
        Stream<Integer> generate = Stream.generate(() -> 1);
        generate.filter(w -> {
            System.out.println(w);
            return w>0;
        });

//        Stream.generate(引數為一個函式, 返回值必須是一個數, 
//        該方法被不停呼叫並將返回值賦予流成為水流中的一員)
        Stream<Double> generate1 = Stream.generate(Math::random);
//        必須有count, 否則在filter中的sout失效
        generate1.filter((w) -> {
            System.out.println(w);
            return w>0.5;
        }).count();

//        建立無限流之iterate
//		  Stream.iterate(種子引數, 迭代函式), 種子參數列示迭代時的初始值, 迭代函式表示每次
//		  執行函式修改上一次迭代函式返回的值, 再作為本次函式的返回值返回,用下面的例子
//		  種子為0, 每次基於上次的結果值加1, 流中儲存的資料為0, 1, 2, 3, 4 ...
//        問題: 每次停止執行後,再次執行的迭代函式是基於上次結束的返回值, 難道是有快取, 
// 		  	停止時列印6002, 再次執行時從6003開始
        Stream<Integer> iterate = Stream.iterate(0, n -> n += 1);
        iterate.filter((w) -> {
            System.out.println(w);
            return w>0.5;
        }).count();
        iterate.forEach(w -> System.out.println(w));

熱烈歡迎大家看下, 一起解決上述程式最後提出的問題

總結

對流的操作加上 Lambda 表示式能夠使程式更加簡潔易懂, 也正是由於簡潔, 不易將這種型別的程式內容書寫太多, 否則過了一段時間, 自己都看不懂這段程式碼.

在後續對大量元素的處理, 可以優先考慮流, 而非集合

相關文章