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.function.Consumer;
import java.util.function.IntConsumer;
/**
* @author 陳楊
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpliteratorDetail {
private IntConsumer intConsumer;
private Consumer consumer;
private List<String> list;
@Before
public void init() {
intConsumer = System.out::println;
consumer = System.out::println;
list = Arrays.asList("Kirito", "Asuna", "Sinon", "Yuuki", "Alice");
}
private void action(IntConsumer intConsumer) {
intConsumer.accept(100);
}
@Test
public void testSpliteratorDetail() {
1、流的建立--源(集合)
// 1、流的建立--源(集合)
/*
Collection集合默認方法 list.stream()
default
Stream<E> stream () {
return StreamSupport.stream(spliterator(), false);
}
@Override
default
Spliterator<E> spliterator () {
return Spliterators.spliterator(this, 0);
}
public static <T> Spliterator<T> spliterator(Collection<? extends T> c,
int characteristics) {
return new IteratorSpliterator<>(Objects.requireNonNull(c),
characteristics);
}*/
// Collector 接口 與 Collectors 靜態類實現
// Spliterator 接口 與 Spliterators 靜態類實現
2、Spliterator 接口
// 2、Spliterator 接口
// Spliterator 接口
// 對數據源中元素進行遍歷或分區
// An object for traversing and partitioning elements of a source.
// 延遲綁定數據源
// 綁定時機:首次遍歷、切分、查詢大小 而不是在建立時
// A <em>late-binding</em> Spliterator binds to the source of elements at the
// point of first traversal, first split, or first query for estimated size,
// rather than at the time the Spliterator is created.
// 非延遲綁定數據源
// 綁定時機:Spliterator建立時 或Spliterator的方法首次調用
// A Spliterator that is not <em>late-binding</em> binds to the source of elements
// at the point of construction or first invocation of any method.
// Spliterator 與 Iterator 的區別:
//
// Spliterator 優點:經過分解和單元素迭代 支持串行與並行
// 比Iterator迭代經過hasNext與next性能更好
// Spliterators, like {@code Iterator}s, are for traversing the elements of a source.
// The Spliterator API was designed to support efficient parallel traversal
// in addition to sequential traversal, by supporting decomposition as well as single-element iteration.
// In addition, the protocol for accessing elements via a Spliterator is designed to impose
// smaller per-element overhead than {@code Iterator}, and to avoid the inherent
// race involved in having separate methods for {@code hasNext()} and {@code next()}.
3、Spliterator特性值
/* public interface Spliterator<T> {
// 3、Spliterator特性值
* Characteristic value signifying that an encounter order is defined for
* elements. If so, this Spliterator guarantees that method
* {@link #trySplit} splits a strict prefix of elements, that method 分割先後對元素加嚴格前綴
* {@link #tryAdvance} steps by one element in prefix order, and that 按照元素的順序前綴遍歷
* {@link #forEachRemaining} performs actions in encounter order. 對剩餘元素按照相遇順序執行action
*
* <p>A {@link Collection} has an encounter order if the corresponding
* {@link Collection#iterator} documents an order. If so, the encounter
* order is the same as the documented order. Otherwise, a collection does
* not have an encounter order.
* 集合是有序的,則文檔是有序的
* 集合是無序的,則文檔是無序的
*
* @apiNote Encounter order is guaranteed to be ascending index order for
* any {@link List}. But no order is guaranteed for hash-based collections
* such as {@link HashSet}. Clients of a Spliterator that reports
* {@code ORDERED} are expected to preserve ordering constraints in
* non-commutative parallel computations.
* 基於索引升序的List 排序-->有序
* 基於Hash散列的HashSet 排序-->無序
* 非併發狀況下指望要保留 有序集合中 元素的順序 以返還給客戶端調用者
public static final int ORDERED = 0x00000010;
* Characteristic value signifying that, for each pair of
* encountered elements {@code x, y}, {@code !x.equals(y)}. This
* applies for example, to a Spliterator based on a {@link Set}.
基於Set的去重DISTINCT
public static final int DISTINCT = 0x00000001;
* Characteristic value signifying that encounter order follows a defined
* sort order. If so, method {@link #getComparator()} returns the associated
* Comparator, or {@code null} if all elements are {@link Comparable} and
* are sorted by their natural ordering.
*
* <p>A Spliterator that reports {@code SORTED} must also report
* {@code ORDERED}.
* 已排序的必定是有序的
*
* @apiNote The spliterators for {@code Collection} classes in the JDK that
* implement {@link NavigableSet} or {@link SortedSet} report {@code SORTED}.
* 若是基於集合的spliterator實現了NavigableSet或SortedSet接口 則爲SORTED
public static final int SORTED = 0x00000004;
* Characteristic value signifying that the value returned from
* {@code estimateSize()} prior to traversal or splitting represents a
* finite size that, in the absence of structural source modification,
* represents an exact count of the number of elements that would be
* encountered by a complete traversal.
* 源中元素個數有限 源元素結構特性未被修改 estimateSize能在完整遍歷過程當中 精準計算
public static final int SIZED = 0x00000040;
* Characteristic value signifying that the source guarantees that
* encountered elements will not be {@code null}. (This applies,
* for example, to most concurrent collections, queues, and maps.)
*
源中元素都不爲null
public static final int NONNULL = 0x00000100;
* Characteristic value signifying that the element source cannot be
* structurally modified; that is, elements cannot be added, replaced, or
* removed, so such changes cannot occur during traversal. A Spliterator
* that does not report {@code IMMUTABLE} or {@code CONCURRENT} is expected
* to have a documented policy (for example throwing
* {@link ConcurrentModificationException}) concerning structural
* interference detected during traversal.
* 源中元素結構不可變
* 源中元素在遍歷過程當中 不能被 添加 替換(包含修改) 刪除
* 若是遍歷時 發送元素結構發生改變 則不能表示爲IMMUTABLE或CONCURRENT 拋出ConcurrentModificationException
public static final int IMMUTABLE = 0x00000400;
* Characteristic value signifying that the element source may be safely
* concurrently modified (allowing additions, replacements, and/or removals)
* by multiple threads without external synchronization. If so, the
* Spliterator is expected to have a documented policy concerning the impact
* of modifications during traversal.
*
* <p>A top-level Spliterator should not report both {@code CONCURRENT} and
* {@code SIZED}, since the finite size, if known, may change if the source
* is concurrently modified during traversal. Such a Spliterator is
* inconsistent and no guarantees can be made about any computation using
* that Spliterator. Sub-spliterators may report {@code SIZED} if the
* sub-split size is known and additions or removals to the source are not
* reflected when traversing.
*
* <p>A top-level Spliterator should not report both {@code CONCURRENT} and
* {@code IMMUTABLE}, since they are mutually exclusive. Such a Spliterator
* is inconsistent and no guarantees can be made about any computation using
* that Spliterator. Sub-spliterators may report {@code IMMUTABLE} if
* additions or removals to the source are not reflected when traversing.
*
* @apiNote Most concurrent collections maintain a consistency policy
* guaranteeing accuracy with respect to elements present at the point of
* Spliterator construction, but possibly not reflecting subsequent
* additions or removals.
* 頂層的Spliterator不能同時擁有CONCURRENT和SIZED特性
* 併發時可能存在對源進行添加、替換(修改)、刪除 以改變元素個數
* 頂層的Spliterator不能同時擁有CONCURRENT和IMMUTABLE特性
* 這兩種特性是互斥的
* 大多數併發集合都保持一致性策略,以確保在拆分器構造點存在的元素的準確性,但可能不反映隨後的添加或刪除
public static final int CONCURRENT = 0x00001000;
* Characteristic value signifying that all Spliterators resulting from
* {@code trySplit()} will be both {@link #SIZED} and {@link #SUBSIZED}.
* (This means that all child Spliterators, whether direct or indirect, will
* be {@code SIZED}.)
*
* <p>A Spliterator that does not report {@code SIZED} as required by
* {@code SUBSIZED} is inconsistent and no guarantees can be made about any
* computation using that Spliterator.
*
* @apiNote Some spliterators, such as the top-level spliterator for an
* approximately balanced binary tree, will report {@code SIZED} but not
* {@code SUBSIZED}, since it is common to know the size of the entire tree
* but not the exact sizes of subtrees.
* 頂層二叉樹是SIZED 但不是SUBSIZED 由於不知道子樹的大小
*
從trySplit返回的子Spliterator都是SIZED 和 SUBSIZED
public static final int SUBSIZED = 0x00004000;
4、Spliterator方法
// 4、Spliterator方法
* If a remaining element exists, performs the given action on it,
* returning {@code true}; else returns {@code false}. If this
* Spliterator is {@link #ORDERED} the action is performed on the
* next element in encounter order. Exceptions thrown by the
* action are relayed to the caller.
*
嘗試遍歷:
若是有下一個元素 就對其執行action
若是是有序的 按照元素相遇順序 對其執行action
若是有異常 將異常信息返回給方法調用者
tryAdvance() 完成了 Iterator的hasNext()與next()
boolean tryAdvance(Consumer<? super T> action);
* Performs the given action for each remaining element, sequentially in
* the current thread, until all elements have been processed or the action
* throws an exception. If this Spliterator is {@link #ORDERED}, actions
* are performed in encounter order. Exceptions thrown by the action
* are relayed to the caller.
按順序遍歷剩餘元素 並對每一個元素執行action 直到遍歷結束 將異常信息返回給方法調用者
default void forEachRemaining(Consumer<? super T> action) {
do { } while (tryAdvance(action));
}
* If this spliterator can be partitioned, returns a Spliterator
* covering elements, that will, upon return from this method, not
* be covered by this Spliterator.
*
* <p>If this Spliterator is {@link #ORDERED}, the returned Spliterator
* must cover a strict prefix of the elements.
*
* <p>Unless this Spliterator covers an infinite number of elements,
* repeated calls to {@code trySplit()} must eventually return {@code null}.
* Upon non-null return:
* <ul>
* <li>the value reported for {@code estimateSize()} before splitting,
* must, after splitting, be greater than or equal to {@code estimateSize()}
* for this and the returned Spliterator; and</li>
* <li>if this Spliterator is {@code SUBSIZED}, then {@code estimateSize()}
* for this spliterator before splitting must be equal to the sum of
* {@code estimateSize()} for this and the returned Spliterator after
* splitting.</li>
* </ul>
*
* <p>This method may return {@code null} for any reason,
* including emptiness, inability to split after traversal has
* commenced, data structure constraints, and efficiency
* considerations.
*
* @apiNote
* An ideal {@code trySplit} method efficiently (without
* traversal) divides its elements exactly in half, allowing
* balanced parallel computation. Many departures from this ideal
* remain highly effective; for example, only approximately
* splitting an approximately balanced tree, or for a tree in
* which leaf nodes may contain either one or two elements,
* failing to further split these nodes. However, large
* deviations in balance and/or overly inefficient {@code
* trySplit} mechanics typically result in poor parallel
* performance.
嘗試對Spliterator中元素進行trySplit
若能進行拆分,則返回一個新的Spliterator對象 裝載已分割的元素
若是分割前有序,分割後也是有序的
分割結果不爲null:
進行有限分割後 最終能獲得非null元素
分割結果爲null:
對有限元素個數的分割:進行無限分割
分割前元素個數爲null
遍歷開始後沒法拆分 數據結構約束 性能考量
Spliterator<T> trySplit();
* Returns an estimate of the number of elements that would be
* encountered by a {@link #forEachRemaining} traversal, or returns {@link
* Long#MAX_VALUE} if infinite, unknown, or too expensive to compute.
*
* <p>If this Spliterator is {@link #SIZED} and has not yet been partially
* traversed or split, or this Spliterator is {@link #SUBSIZED} and has
* not yet been partially traversed, this estimate must be an accurate
* count of elements that would be encountered by a complete traversal.
* Otherwise, this estimate may be arbitrarily inaccurate, but must decrease
* as specified across invocations of {@link #trySplit}.
*
* @apiNote
* Even an inexact estimate is often useful and inexpensive to compute.
* For example, a sub-spliterator of an approximately balanced binary tree
* may return a value that estimates the number of elements to be half of
* that of its parent; if the root Spliterator does not maintain an
* accurate count, it could estimate size to be the power of two
* corresponding to its maximum depth.
估算元素數量(即將遍歷的元素個數)
若是元素數量無限 未知 或計算成本很昂貴 返回Long.Max_Value
若是Spliterator是一個SIZED或SUBSIZED estimate則是完整遍歷所須要的值(accurate精確)
long estimateSize();
* Convenience method that returns {@link #estimateSize()} if this
* Spliterator is {@link #SIZED}, else {@code -1}.
characteristic.SIZED -->返回肯定的大小 不然爲 -1L
default long getExactSizeIfKnown() {
return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
}
* Returns a set of characteristics of this Spliterator and its
* elements. The result is represented as ORed values from {@link
* #ORDERED}, {@link #DISTINCT}, {@link #SORTED}, {@link #SIZED},
* {@link #NONNULL}, {@link #IMMUTABLE}, {@link #CONCURRENT},
* {@link #SUBSIZED}. Repeated calls to {@code characteristics()} on
* a given spliterator, prior to or in-between calls to {@code trySplit},
* should always return the same result.
*
* <p>If a Spliterator reports an inconsistent set of
* characteristics (either those returned from a single invocation
* or across multiple invocations), no guarantees can be made
* about any computation using this Spliterator.
*
* @apiNote The characteristics of a given spliterator before splitting
* may differ from the characteristics after splitting. For specific
* examples see the characteristic values {@link #SIZED}, {@link #SUBSIZED}
* and {@link #CONCURRENT}.
*
* @return a representation of characteristics
返回Spliterator與其元素的一個特性值標識
在分割期間或以前 其元素的特性不變
分割先後若元素的特性發生了變動 對其進行計算行爲是不能受到保證的
int characteristics();
* Returns {@code true} if this Spliterator's {@link
* #characteristics} contain all of the given characteristics.
判斷是否包含此元素特性
default boolean hasCharacteristics(int characteristics) {
return (characteristics() & characteristics) == characteristics;
}
* If this Spliterator's source is {@link #SORTED} by a {@link Comparator},
* returns that {@code Comparator}. If the source is {@code SORTED} in
* {@linkplain Comparable natural order}, returns {@code null}. Otherwise,
* if the source is not {@code SORTED}, throws {@link IllegalStateException}.
若是source是有序的:
若是是按照比較器進行排序 則返回該比較器
若是是Comparable natural order 則返回null
若是source是無序的 拋出IllegalStateException異常
default Comparator<? super T> getComparator() {
throw new IllegalStateException();
}
* A Spliterator specialized for primitive values.
* 針對於原生類型值的特化分割器
*
* @param <T> the type of elements returned by this Spliterator.
* The type must be a wrapper type for a primitive type,
* such as {@code Integer} for the primitive {@code int} type.
* @param <T_CONS> the type of primitive consumer. The type must be a
* primitive specialization of {@link java.util.function.Consumer} for
* {@code T}, such as {@link java.util.function.IntConsumer} for {@code Integer}.
* @param <T_SPLITR> the type of primitive Spliterator. The type must be
* a primitive specialization of Spliterator for {@code T}, such as
* {@link Spliterator.OfInt} for {@code Integer}.
*
* @see Spliterator.OfInt
* @see Spliterator.OfLong
* @see Spliterator.OfDouble
* @since 1.8
* T Spliterator返回的元素類型:原生包裝類型
* T_CONS primitive consumer :java.util.function.IntConsumer對Integer的原生特化
* T_SPLITR primitive Spliterator :Spliterator.OfInt對Integer的原生特化
*
public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
extends Spliterator<T> {
@Override
T_SPLITR trySplit();
@SuppressWarnings("overloads")
boolean tryAdvance(T_CONS action);
@SuppressWarnings("overloads")
default void forEachRemaining(T_CONS action) {
do { } while (tryAdvance(action));
}
}
* A Spliterator specialized for {@code int} values.
* @since 1.8
public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {
@Override
OfInt trySplit();
@Override
boolean tryAdvance(IntConsumer action);
@Override
default void forEachRemaining(IntConsumer action) {
do { } while (tryAdvance(action));
}
5、Consumer 與 IntConsumer、LongConsumer、DoubleConsumer
5、Consumer 與 IntConsumer、LongConsumer、DoubleConsumer
// Consumer 與 IntConsumer 爲何能進行強制類型轉換?
// Consumer 與 IntConsumer 之間沒有繼承關係 層次上無關係
// Consumer 與 IntConsumer 當傳入的參數是整型int,Integer時 會自動進行裝箱拆箱
// ((IntConsumer) action::accept) 是Lambda表達式
// Lambda表達式 是一種匿名函數 沒有方法聲明 具備上下文自動推測類型功能
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code IntConsumer} then it is cast
* to {@code IntConsumer} and passed to
* {@link #tryAdvance(java.util.function.IntConsumer)}; otherwise
* the action is adapted to an instance of {@code IntConsumer}, by
* boxing the argument of {@code IntConsumer}, and then passed to
* {@link #tryAdvance(java.util.function.IntConsumer)}.
@Override
default boolean tryAdvance(Consumer<? super Integer> action) {
if (action instanceof IntConsumer) {
return tryAdvance((IntConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfInt.tryAdvance((IntConsumer) action::accept)");
return tryAdvance((IntConsumer) action::accept);
}
}
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code IntConsumer} then it is cast
* to {@code IntConsumer} and passed to
* {@link #forEachRemaining(java.util.function.IntConsumer)}; otherwise
* the action is adapted to an instance of {@code IntConsumer}, by
* boxing the argument of {@code IntConsumer}, and then passed to
* {@link #forEachRemaining(java.util.function.IntConsumer)}.
@Override
default void forEachRemaining(Consumer<? super Integer> action) {
if (action instanceof IntConsumer) {
forEachRemaining((IntConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfInt.forEachRemaining((IntConsumer) action::accept)");
forEachRemaining((IntConsumer) action::accept);
}
}
}
* A Spliterator specialized for {@code long} values.
* @since 1.8
public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> {
@Override
OfLong trySplit();
@Override
boolean tryAdvance(LongConsumer action);
@Override
default void forEachRemaining(LongConsumer action) {
do { } while (tryAdvance(action));
}
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code LongConsumer} then it is cast
* to {@code LongConsumer} and passed to
* {@link #tryAdvance(java.util.function.LongConsumer)}; otherwise
* the action is adapted to an instance of {@code LongConsumer}, by
* boxing the argument of {@code LongConsumer}, and then passed to
* {@link #tryAdvance(java.util.function.LongConsumer)}.
@Override
default boolean tryAdvance(Consumer<? super Long> action) {
if (action instanceof LongConsumer) {
return tryAdvance((LongConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfLong.tryAdvance((LongConsumer) action::accept)");
return tryAdvance((LongConsumer) action::accept);
}
}
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code LongConsumer} then it is cast
* to {@code LongConsumer} and passed to
* {@link #forEachRemaining(java.util.function.LongConsumer)}; otherwise
* the action is adapted to an instance of {@code LongConsumer}, by
* boxing the argument of {@code LongConsumer}, and then passed to
* {@link #forEachRemaining(java.util.function.LongConsumer)}.
@Override
default void forEachRemaining(Consumer<? super Long> action) {
if (action instanceof LongConsumer) {
forEachRemaining((LongConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfLong.forEachRemaining((LongConsumer) action::accept)");
forEachRemaining((LongConsumer) action::accept);
}
}
}
* A Spliterator specialized for {@code double} values.
* @since 1.8
public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> {
@Override
OfDouble trySplit();
@Override
boolean tryAdvance(DoubleConsumer action);
@Override
default void forEachRemaining(DoubleConsumer action) {
do { } while (tryAdvance(action));
}
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code DoubleConsumer} then it is
* cast to {@code DoubleConsumer} and passed to
* {@link #tryAdvance(java.util.function.DoubleConsumer)}; otherwise
* the action is adapted to an instance of {@code DoubleConsumer}, by
* boxing the argument of {@code DoubleConsumer}, and then passed to
* {@link #tryAdvance(java.util.function.DoubleConsumer)}.
@Override
default boolean tryAdvance(Consumer<? super Double> action) {
if (action instanceof DoubleConsumer) {
return tryAdvance((DoubleConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfDouble.tryAdvance((DoubleConsumer) action::accept)");
return tryAdvance((DoubleConsumer) action::accept);
}
}
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code DoubleConsumer} then it is
* cast to {@code DoubleConsumer} and passed to
* {@link #forEachRemaining(java.util.function.DoubleConsumer)};
* otherwise the action is adapted to an instance of
* {@code DoubleConsumer}, by boxing the argument of
* {@code DoubleConsumer}, and then passed to
* {@link #forEachRemaining(java.util.function.DoubleConsumer)}.
@Override
default void forEachRemaining(Consumer<? super Double> action) {
if (action instanceof DoubleConsumer) {
forEachRemaining((DoubleConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfDouble.forEachRemaining((DoubleConsumer) action::accept)");
forEachRemaining((DoubleConsumer) action::accept);
}
}
}
}*/
6、Consumer 與 IntConsumer 的強制類型轉換測試
// 6、Consumer 與 IntConsumer 的強制類型轉換測試
// 傳入面向對象 對象
this.action(intConsumer);
// 傳入Lambda表達式 函數式編程
this.action(intConsumer::accept);
this.action(value -> intConsumer.accept(value));
this.action(consumer::accept);
this.action(value -> consumer.accept(value));
// 面向對象強制類型轉換 報錯java.lang.ClassCastException
// this.action((IntConsumer) consumer);
// this.action(((IntConsumer) consumer)::accept);
// this.action(t -> ((IntConsumer) consumer).accept(t));
// 函數式編程強制類型轉換 Lambda表達式沒變
this.action((IntConsumer) consumer::accept);
this.action((IntConsumer) (t -> consumer.accept(t)));
this.action((IntConsumer) t -> consumer.accept(t));
7、Iterator-based Spliterators 與 StreamSupport底層實現
// 7、Iterator-based Spliterators 與 StreamSupport底層實現
// Iterator-based Spliterators
/*
* A Spliterator using a given Iterator for element
* operations. The spliterator implements {@code trySplit} to
* permit limited parallelism.
* spliterator利用trySplit實現有限的並行化操做
*
* static class IteratorSpliterator<T> implements Spliterator<T> {}
*/
/*
* Low-level utility methods for creating and manipulating streams.
* 用於建立和操做流的底層實用程序方法
*
* <p>This class is mostly for library writers presenting stream views
* of data structures; most static stream methods intended for end users are in
* the various {@code Stream} classes.
* StreamSupport提供數據結構的流視圖的library 大多數爲終端用戶使用的靜態流方法在Stream類中
*
* @since 1.8
*
public final class StreamSupport {
* Creates a new sequential or parallel {@code Stream} from a
* {@code Spliterator}.
*
*
* <p>The spliterator is only traversed, split, or queried for estimated
* size after the terminal operation of the stream pipeline commences.
* 僅在流管道的終端操做開始後,才遍歷、拆分或查詢spliterator的估計大小。
*
* <p>It is strongly recommended the spliterator report a characteristic of
* {@code IMMUTABLE} or {@code CONCURRENT}, or be
* <a href="../Spliterator.html#binding">late-binding</a>. Otherwise,
* {@link #stream(java.util.function.Supplier, int, boolean)} should be used
* to reduce the scope of potential interference with the source. See
* <a href="package-summary.html#NonInterference">Non-Interference</a> for
* more details.
* 強烈建議對spliterator設置characteristic(IMMUTABLE CONCURRENT late-binding)
* 以減小潛在的干擾源範圍
*
public static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel) {
Objects.requireNonNull(spliterator);
return new ReferencePipeline.Head<>(spliterator,
StreamOpFlag.fromCharacteristics(spliterator),
parallel);
}
}*/
8、流源分析
// 8、流源分析
/*
流源的建立
Abstract base class for an intermediate pipeline stage or pipeline source
stage implementing whose elements are of type {@code U}.
抽象基類:用於實現其元素類型爲{@code U}的中間管道階段或管道源階段
ReferencePipeline 操做引用類型 (將源階段 與 [0,n)箇中間操做階段 看作一個對象)
* @param <P_IN> type of elements in the upstream source
* @param <P_OUT> type of elements in produced by this stage
abstract class ReferencePipeline<P_IN, P_OUT>
extends AbstractPipeline<P_IN, P_OUT, Stream<P_OUT>>
implements Stream<P_OUT> {
* 源階段
* Source stage of a ReferencePipeline.
*
* @param <E_IN> type of elements in the upstream source
* @param <E_OUT> type of elements in produced by this stage
ReferencePipeline中靜態內部類Head
static class Head<E_IN, E_OUT> extends ReferencePipeline<E_IN, E_OUT>
*
* 注意:
* 流自己不持有數據
* 數據的持有者:流的數據源(集合、數組等)
* 流關注對數據的計算
*/
/* 抽象基類: 抽象管道AbstractPipeline 流接口及 其特化的核心實現
管理流管道 建立 與 評估
* Abstract base class for "pipeline" classes, which are the core
* implementations of the Stream interface and its primitive specializations.
* Manages construction and evaluation of stream pipelines.
*
* <p>A concrete intermediate stage is generally built from an
* {@code AbstractPipeline}, a shape-specific pipeline class which extends it
* (e.g., {@code IntPipeline}) which is also abstract, and an operation-specific
* concrete class which extends that. {@code AbstractPipeline} contains most of
* the mechanics of evaluating the pipeline, and implements methods that will be
* used by the operation; the shape-specific classes add helper methods for
* dealing with collection of results into the appropriate shape-specific
* containers.
*
*
* <p>After chaining a new intermediate operation, or executing a terminal
* operation, the stream is considered to be consumed, and no more intermediate
* or terminal operations are permitted on this stream instance.
* 在鏈式添加中間操做或一個終止操做後 流視作被消費
* 流只能被消費一次 已消費-->不容許在此流實例中存在更多的中間操做或終止操做
*
* @implNote
* <p>For sequential streams, and parallel streams without
* <a href="package-summary.html#StreamOps">stateful intermediate
* operations</a>, parallel streams, pipeline evaluation is done in a single
* pass that "jams" all the operations together. For parallel streams with
* stateful operations, execution is divided into segments, where each
* stateful operations marks the end of a segment, and each segment is
* evaluated separately and the result used as the input to the next
* segment. In all cases, the source data is not consumed until a terminal
* operation begins.
* 串行流 與 無狀態的並行流
* 流的消費 是將中間的操做進行「jams」(打包放一塊兒)對流中每一個元素執行action-->single pass
*
* 有狀態的並行流
* 執行分紅segments 分別對segment執行有狀態操做 並將其結果做爲下一個segment輸入
*
* 在任何狀況下,有且只有在一個終止操做被調用時 流真正被消費
abstract class AbstractPipeline<E_IN, E_OUT, S extends BaseStream<E_OUT, S>>
extends PipelineHelper<E_OUT> implements BaseStream<E_OUT, S>
AbstractPipeline的構造方法
AbstractPipeline(Supplier<? extends Spliterator<?>> source,
int sourceFlags, boolean parallel) {}
AbstractPipeline(Spliterator<?> source,
int sourceFlags, boolean parallel) {}
同一時間構造同一個AbstractPipeline 有且只有調用AbstractPipeline構造方法之一
sourceSpliterator與sourceSupplier
同一時間只能存在其一
當流被消費後 若not null 要設置爲null
只能被消費一次
private Spliterator<?> sourceSpliterator;
private Supplier<? extends Spliterator<?>> sourceSupplier;
*/
/*
針對於流源的foreach
Optimized sequential terminal operations for the head of the pipeline
@Override
public void forEach(Consumer<? super E_OUT> action) {
if (!isParallel()) {
sourceStageSpliterator().forEachRemaining(action);
}
else {
super.forEach(action);
}
}
Terminal operations from Stream
@Override
public void forEach(Consumer<? super P_OUT> action) {
evaluate(ForEachOps.makeRef(action, false));
}
*/
9、Array.asList()流源遍歷注意事項
// 9、Array.asList()流源遍歷注意事項
/*
爲何 未調用IteratorSpliterator.forEachRemaining()
list.stream().forEach(System.out::println); 執行過程分析
Arrays.asList()
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable{
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(a, Spliterator.ORDERED);
}
}
public static <T> Spliterator<T> spliterator(Object[] array,
int additionalCharacteristics) {
return new ArraySpliterator<>(Objects.requireNonNull(array),
additionalCharacteristics);
}
@Override
public void forEach(Consumer<? super E_OUT> action) {
if (!isParallel()) {
sourceStageSpliterator().forEachRemaining(action);
}
else {
super.forEach(action);
}
}
@SuppressWarnings("unchecked")
@Override
public void forEachRemaining(Consumer<? super T> action) {
Object[] a; int i, hi; // hoist accesses and checks from loop
if (action == null)
throw new NullPointerException();
if ((a = array).length >= (hi = fence) &&
(i = index) >= 0 && i < (index = hi)) {
do { action.accept((T)a[i]); } while (++i < hi);
}
}*/
System.out.println(list.getClass());
// Arrays中靜態內部類ArrayList (class java.util.Arrays$ArrayList)
// @Override public Spliterator<E> spliterator(){}
// 調用ArraySpliterator.forEachRemaining()實現
list.stream().forEach(System.out::println);
// 普通集合遍歷 Iterable 中的 forEach
// 效率高
list.forEach(System.out::println);
}
}
10、測試結果
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.2.RELEASE)
2019-02-20 18:09:13.662 INFO 2224 --- [ main] c.j.d.j.S.S.B.SpliteratorDetail : Starting SpliteratorDetail on DESKTOP-87RMBG4 with PID 2224 (started by 46250 in E:\IdeaProjects\design)
2019-02-20 18:09:13.663 INFO 2224 --- [ main] c.j.d.j.S.S.B.SpliteratorDetail : No active profile set, falling back to default profiles: default
2019-02-20 18:09:14.133 INFO 2224 --- [ main] c.j.d.j.S.S.B.SpliteratorDetail : Started SpliteratorDetail in 0.653 seconds (JVM running for 1.335)
100
100
100
100
100
100
100
100
class java.util.Arrays$ArrayList
Kirito
Asuna
Sinon
Yuuki
Alice
Kirito
Asuna
Sinon
Yuuki
Alice