Stream流與Lambda表達式(五) Stream BaseStream AutoCloseable源碼解讀

package com.java.design.java8.Stream.StreamDetail;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;

/**
 * @author 陳楊
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class StreamDetail {

    private List<Integer> integerList;

    @Before
    public void init() {
        integerList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
    }

    @Test
    public void testStreamDetail() {

一、流的定義

        //    Stream :  A sequence of elements supporting sequential and parallel aggregate operations.
        //    流: 支持 串行、並行 聚合操作 元素序列

二、流的創建

        //    流的創建:
        //    Collection.stream()  Collection.parallelStream()
        //    Stream.generate
        System.out.println("-----------------------------------------\n");
        System.out.println("以Stream.generate方法生成流");
        Stream<String> generate = Stream.generate(UUID.randomUUID()::toString);
        generate.findFirst().ifPresent(System.out::println);
        System.out.println("-----------------------------------------\n");

三、對象引用流

        //    對象引用流
        //    Stream , which is a stream of object references

四、流的計算

        //    流的計算:    stream pipeline
        //    To perform a computation, stream operations are composed into a  stream pipeline.

五、流管道組成

        //    流管道組成:  源數據source-->數組、集合、生成器函數、IO通道等
        //                 [0,n) 中間操作(intermediate operations) 一個流轉換 爲 另一個新流
        //                 終止操作(terminal operation)產生一個結果 或有副作用(修改流中元素 屬性或狀態)
        //    A stream pipeline consists of a source (which  might be an array,
        //    a collection, a generator function, an I/O channel,etc),
        //    zero or more <em>intermediate operations</em> (which transform a
        //    stream into another stream, such as {@link Stream#filter(Predicate)}), and a
        //    <em>terminal operation</em> (which produces a result or side-effect, such
        //    as {@link Stream#count()} or {@link Stream#forEach(Consumer)}).

六、流的消費

        //    流的消費:  流中對於源數據的計算 有且僅有在終止操作觸發時纔會被調用
        //               流中元素只有在被需要時纔會被消費
        //               lazy(惰性): 如果沒有終止操作 那麼一系列的中間操作都不會被執行
        //               stream流操作只會執行一次: stream中有一個容器 將所有中間操作打包 放入容器中
        //               調用終止操作時 觸發容器的鏈式中間操作 將流中每一個元素 應用於中間業務邏輯
        //    Streams are lazy; computation on the source data is only performed when the
        //    terminal operation is initiated, and source elements are consumed only as needed.
        //    流創建後 只能被消費一次 否則拋異常
        //    除非流被設計成爲顯示併發修改的流如ConcurrentHashMap 否則未期望或錯誤的行爲就會在執行時產生
        //    Unless the source was explicitly designed for concurrent modification
        //    (such as a ConcurrentHashMap),unpredictable or erroneous behavior may result
        //    from modifying the stream source while it is being queried.
        //    java.lang.IllegalStateException: stream has already been operated upon or closed

七、 Lambda表達式的正確行爲

        //    Lambda表達式的正確行爲:
        //    To preserve correct behavior,these <em>behavioral parameters</em>:

        //    must be <a href="package-summary.html#NonInterference">non-interfering</a>
        //    (they do not modify the stream source);

        //    in most cases must be <a href="package-summary.html#Statelessness">stateless</a>
        //    (their result should not depend on any state that might change during execution
        //    of the stream pipeline).

八、流與集合

//    流與集合:
//    集合關注的是對元素的管理與訪問
//    流不會直接提供直接訪問或操作其元素的方法
//    流提供聲明性描述: 源 與 建立於源之上的聚合計算執行操作
//    如果流沒有提供預期的功能 可執行受控遍歷(iterator、spliterator)
//    Collections and streams, while bearing some superficial similarities,
//    have different goals.  Collections are primarily concerned with the efficient
//    management of, and access to, their elements.  By contrast, streams do not
//    provide a means to directly access or manipulate their elements, and are
//    instead concerned with declaratively describing their source and the
//    computational operations which will be performed in aggregate on that source.
//    However, if the provided stream operations do not offer the desired
//    functionality, the {@link #iterator()} and {@link #spliterator()} operations
//    can be used to perform a controlled traversal.

九、 流的MapReduce操作

//   流的MapReduce操作  求集合 每個元素的2倍 之和
//   此例中:Integer 每執行一次reduce操作 觸發 該元素的map操作一次
System.out.println(integerList.stream().map(i -> 2 * i).reduce(0, Integer::sum));
System.out.println("-----------------------------------------\n");

十、流資源自動關閉 AutoCloseable接口實現

package com.java.design.java8.Stream.StreamDetail;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 陳楊
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class AutoCloseableTest implements AutoCloseable {

    /*
     *      An object that may hold resources (such as file or socket handles)
     *      until it is closed. The {@link #close()} method of an {@code AutoCloseable}
     *      object is called automatically when exiting a {@code
     *      try}-with-resources block for which the object has been declared in
     *      the resource specification header. This construction ensures prompt
     *      release, avoiding resource exhaustion exceptions and errors that
     *      may otherwise occur.
     *
     *      實現AutoCloseable接口:
     *          使用try--with--resources 代碼塊 替代 try--catch--finally
     *          在代碼塊運行完畢後 自動實現 資源的關閉
     *      public interface AutoCloseable {
     *               void close() throws Exception;
     *                }
     */

    public void doSomeThing() {

        System.out.println("method doSomeThing invoked!");
    }


    @Override
    public void close() throws Exception {
        System.out.println("method close invoked!");
    }


    @Test
    public void testAutoCloseable() throws Exception {

        try (AutoCloseableTest autoCloseableTest = new AutoCloseableTest()) {
            autoCloseableTest.doSomeThing();
        }
    }


}

十一、認識BaseStream 與 closeHandler

package com.java.design.java8.Stream.StreamDetail.BaseStreamDetail;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * @author 陳楊
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class BaseStreamDetail {

    private List<String> list;
    private NullPointerException myException;

    @Before
    public void init() {
        list = Arrays.asList("Kirito", "Asuna", "Illyasviel", "Sakura");
        myException = new NullPointerException("my NullPointerException");
    }

    @Test
    public void testBaseStreamDetail() {

        // public interface Stream<T> extends BaseStream<T, Stream<T>>

      /*public interface BaseStream<T, S extends BaseStream<T, S>> extends AutoCloseable {

         Iterator<T> iterator();

       * Returns a spliterator for the elements of this stream.

         Spliterator<T> spliterator();


       *  當終止操作應用於流時 判斷其是否並行
       *  當執行終止操作之後 執行isParallel() 會得到不可預期的結果
       *    此方法需適用於終止操作之前
       *
       * Returns whether this stream, if a terminal operation were to be executed,
       * would execute in parallel.  Calling this method after invoking an
       * terminal stream operation method may yield unpredictable results.
       *
           boolean isParallel();


       * 返回一個等價的串行流
       *     流本身已經是串行 或 流的狀態已被修改爲串行
       *
       * Returns an equivalent stream that is sequential.  May return
       * itself, either because the stream was already sequential, or because
       * the underlying stream state was modified to be sequential.
       *
        S sequential();


       * 返回一個等價的並行流
       *     流本身已經是並行 或 流的狀態已被修改爲並行
       *
       * Returns an equivalent stream that is parallel.  May return
       * itself, either because the stream was already parallel, or because
       * the underlying stream state was modified to be parallel.
       *
          S parallel();


       * 返回一個等價的無序流
       *     流本身已經是無序 或 流的狀態已被修改爲無序
       *
       * Returns an equivalent stream that is
       * <a href="package-summary.html#Ordering">unordered</a>.  May return
       * itself, either because the stream was already unordered, or because
       * the underlying stream state was modified to be unordered.
       *
          S unordered();


       * 返回一個等價的流 有close handler
       *     close handler當流close()方法調用時觸發
       *     調用順序:close handlers被添加先後順序
       *
       *     所有的close handlers都會被調用 即使出現了異常
       *     如果任意close handler拋出異常
       *             那麼第一個異常會傳遞給調用段
       *             其他異常(剩餘或被抑制)會傳遞給調用段
       *                     除非其中有與第一個異常相同的異常(相同對象)  因爲相同異常不能抑制自身
       *
       * Returns an equivalent stream with an additional close handler.  Close
       * handlers are run when the {@link #close()} method
       * is called on the stream, and are executed in the order they were
       * added.  All close handlers are run, even if earlier close handlers throw
       * exceptions.  If any close handler throws an exception, the first
       * exception thrown will be relayed to the caller of {@code close()}, with
       * any remaining exceptions added to that exception as suppressed exceptions
       * (unless one of the remaining exceptions is the same exception as the
       * first exception, since an exception cannot suppress itself.)  May
       * return itself.
       *
       * @param closeHandler A task to execute when the stream is closed
       * @return a stream with a handler that is run if the stream is closed

          S onClose(Runnable closeHandler);


       * 關閉流 調用流管道中的close handlers
       *
       * Closes this stream, causing all close handlers for this stream pipeline  to be called.

          @Override
          void close();
      }*/


        try (Stream<String> stream = list.stream()) {
            stream.onClose(() -> {
                System.out.println("close handler first");
                // throw new NullPointerException("null pointer exception 1");
                throw myException;
            }).onClose(() -> {
                System.out.println("close handler second");
                // throw new NullPointerException("null pointer exception 2");
                throw myException;
            }).onClose(() -> {
                System.out.println("close handler third");
                // throw new NullPointerException("null pointer exception 3");
                throw myException;
            }).forEach(System.out::println);
        }


    }


}

十二、測試結果

testStreamDetail測試
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.2.RELEASE)

2019-02-20 17:40:31.060  INFO 15872 --- [           main] c.j.d.j.S.StreamDetail.StreamDetail      : Starting StreamDetail on DESKTOP-87RMBG4 with PID 15872 (started by 46250 in E:\IdeaProjects\design)
2019-02-20 17:40:31.062  INFO 15872 --- [           main] c.j.d.j.S.StreamDetail.StreamDetail      : No active profile set, falling back to default profiles: default
2019-02-20 17:40:31.584  INFO 15872 --- [           main] c.j.d.j.S.StreamDetail.StreamDetail      : Started StreamDetail in 0.728 seconds (JVM running for 1.461)
-----------------------------------------

以Stream.generate方法生成流
2742c0e9-7bdb-4c7e-88c9-b5d94684215c
-----------------------------------------

90
-----------------------------------------
AutoCloseableTest測試
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.2.RELEASE)

2019-02-20 17:39:45.456  INFO 16320 --- [           main] c.j.d.j.S.S.AutoCloseableTest            : Starting AutoCloseableTest on DESKTOP-87RMBG4 with PID 16320 (started by 46250 in E:\IdeaProjects\design)
2019-02-20 17:39:45.457  INFO 16320 --- [           main] c.j.d.j.S.S.AutoCloseableTest            : No active profile set, falling back to default profiles: default
2019-02-20 17:39:45.956  INFO 16320 --- [           main] c.j.d.j.S.S.AutoCloseableTest            : Started AutoCloseableTest in 0.716 seconds (JVM running for 1.433)
method doSomeThing invoked!
method close invoked!
testBaseStreamDetail測試
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.2.RELEASE)

2019-02-20 17:46:41.886  INFO 15216 --- [           main] c.j.d.j.S.S.B.BaseStreamDetail           : Starting BaseStreamDetail on DESKTOP-87RMBG4 with PID 15216 (started by 46250 in E:\IdeaProjects\design)
2019-02-20 17:46:41.887  INFO 15216 --- [           main] c.j.d.j.S.S.B.BaseStreamDetail           : No active profile set, falling back to default profiles: default
2019-02-20 17:46:42.435  INFO 15216 --- [           main] c.j.d.j.S.S.B.BaseStreamDetail           : Started BaseStreamDetail in 0.762 seconds (JVM running for 1.48)
Kirito
Asuna
Illyasviel
Sakura
close handler first
close handler second
close handler third

java.lang.NullPointerException: my NullPointerException

Process finished with exit code -1


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章