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() {
1、流的定義
// Stream : A sequence of elements supporting sequential and parallel aggregate operations.
// 流: 支持 串行、並行 聚合操做 元素序列
2、流的建立
// 流的建立:
// 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");
3、對象引用流
// 對象引用流
// Stream , which is a stream of object references
4、流的計算
// 流的計算: stream pipeline
// To perform a computation, stream operations are composed into a stream pipeline.
5、流管道組成
// 流管道組成: 源數據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)}).
6、流的消費
// 流的消費: 流中對於源數據的計算 有且僅有在終止操做觸發時纔會被調用
// 流中元素只有在被須要時纔會被消費
// 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
7、 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).
8、流與集合
// 流與集合:
// 集合關注的是對元素的管理與訪問
// 流不會直接提供直接訪問或操做其元素的方法
// 流提供聲明性描述: 源 與 創建於源之上的聚合計算執行操做
// 若是流沒有提供預期的功能 可執行受控遍歷(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.
9、 流的MapReduce操做
// 流的MapReduce操做 求集合 每一個元素的2倍 之和
// 此例中:Integer 每執行一次reduce操做 觸發 該元素的map操做一次
System.out.println(integerList.stream().map(i -> 2 * i).reduce(0, Integer::sum));
System.out.println("-----------------------------------------\n");
10、流資源自動關閉 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();
}
}
}
11、認識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);
}
}
}
12、測試結果
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