Stream流與Lambda表達式(六) SpliteratorDetail

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 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()}.

三、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
     *  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));
        }

五、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(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);
    }


}*/

八、流源分析

 // 八、流源分析
 /*
 流源的創建

 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.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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章