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



陈杨
12 声望3 粉丝

不闻不若闻之,闻之不若见之,见之不若知之,知之不若行之,学至于行而止矣;行之,明也!