Stream流与Lambda表达式(五) Stream BaseStream AutoCloseable源码解读

9次阅读

共计 10365 个字符,预计需要花费 26 分钟才能阅读完成。

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

正文完
 0