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 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 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 intermediate operations (which transform a // stream into another stream, such as {@link Stream#filter(Predicate)}), and a // terminal operation (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 behavioral parameters: // must be non-interfering // (they do not modify the stream source); // in most cases must be stateless // (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 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 extends BaseStream > /*public interface BaseStream > extends AutoCloseable { Iterator iterator(); * Returns a spliterator for the elements of this stream. Spliterator 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 * unordered. 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 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: default2019-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: default2019-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: default2019-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)KiritoAsunaIllyasvielSakuraclose handler firstclose handler secondclose handler thirdjava.lang.NullPointerException: my NullPointerExceptionProcess finished with exit code -1