Stream流與Lambda表示式(六) SpliteratorDetail
摘要:
package com.java.design.java8.Stream.StreamDetail.BaseStreamDetail;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWi...
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() {
一、流的建立--源(集合)
// 一、流的建立--源(集合) /* 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 靜態類實現
二、Spliterator 介面
//二、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 ofa 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()}.
三、Spliterator特性值
/* public interface Spliterator<T> { // 三、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;
四、Spliterator方法
//四、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 *TSpliterator返回的元素型別:原生包裝型別 *T_CONSprimitive 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)); }
五、Consumer 與 IntConsumer、LongConsumer、DoubleConsumer
五、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); } } } }*/
六、Consumer 與 IntConsumer 的強制型別轉換測試
// 六、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));
七、Iterator-based Spliterators 與 StreamSupport底層實現
// 七、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(IMMUTABLECONCURRENT 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); } }*/
八、流源分析
// 八、流源分析 /* 流源的建立 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)); } */
九、Array.asList()流源遍歷注意事項
// 九、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); } }
十、測試結果
._______ _ _ /\\ / ___'_ __ _ _(_)_ ____ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/___)| |_)| | | | | || (_| |) ) ) ) '|____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot ::(v2.1.2.RELEASE) 2019-02-20 18:09:13.662INFO 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.663INFO 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.133INFO 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