Stream 흐름 과 Lambda 표현 식 (6) Spliterator Detail

35581 단어 lambdastream자바
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 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. 흐름 의 생 성 - 소스 (집합)
//  、    -- (  )
/*
Collection       list.stream()

default
Stream stream () {
    return StreamSupport.stream(spliterator(), false);
}

@Override
default
Spliterator spliterator () {
    return Spliterators.spliterator(this, 0);
}

public static  Spliterator spliterator(Collection extends T> c,
int characteristics) {
    return new IteratorSpliterator<>(Objects.requireNonNull(c),
            characteristics);
}*/

//  Collector        Collectors        
//  Spliterator      Spliterators      

2. Spliterator 인터페이스
//   、Spliterator   

//  Spliterator   
//                
//  An object for traversing and partitioning elements of a source.
//         
//          :    、  、            
//  A  late-binding 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 late-binding 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 {

//  、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
     *
     * 

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. * *

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. * *

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. * *

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

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 방법
//   、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.
     *
     * 

If this Spliterator is {@link #ORDERED}, the returned Spliterator * must cover a strict prefix of the elements. * *

Unless this Spliterator covers an infinite number of elements, * repeated calls to {@code trySplit()} must eventually return {@code null}. * Upon non-null return: *

    *
  • 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
  • *
  • 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.
  • *
* *

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 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. * *

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. * *

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 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 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 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> extends Spliterator { @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 { @Override OfInt trySplit(); @Override boolean tryAdvance(IntConsumer action); @Override default void forEachRemaining(IntConsumer action) { do { } while (tryAdvance(action)); }


5. 소비자 와 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 {

        @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 {

        @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 의 강제 유형 전환 테스트
//  、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 Spreators 와 Stream Support 바 텀 실현
//  、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 implements Spliterator {}
 */


/*
 * Low-level utility methods for creating and manipulating streams.
 *                  
 *
 * 

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}. * * *

The spliterator is only traversed, split, or queried for estimated * size after the terminal operation of the stream pipeline commences. * , 、 spliterator 。 * *

It is strongly recommended the spliterator report a characteristic of * {@code IMMUTABLE} or {@code CONCURRENT}, or be * late-binding. Otherwise, * {@link #stream(java.util.function.Supplier, int, boolean)} should be used * to reduce the scope of potential interference with the source. See * Non-Interference for * more details. * spliterator characteristic(IMMUTABLE CONCURRENT late-binding) * * public static Stream stream(Spliterator spliterator, boolean parallel) { Objects.requireNonNull(spliterator); return new ReferencePipeline.Head<>(spliterator, StreamOpFlag.fromCharacteristics(spliterator), parallel); } }*/


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   type of elements in the upstream source
 * @param  type of elements in produced by this stage

  abstract class ReferencePipeline
         extends AbstractPipeline>
         implements Stream  {


 *    
 * Source stage of a ReferencePipeline.
 *
 * @param  type of elements in the upstream source
 * @param  type of elements in produced by this stage

 ReferencePipeline      Head
 static class Head extends ReferencePipeline

 *
 *   :
 *             
 *           :     (  、   )
 *              
 */


/*     :     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.
 *
 * 

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. * * *

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 *

For sequential streams, and parallel streams without * stateful intermediate * operations, 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> extends PipelineHelper implements BaseStream 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 () 스 트림 스 트 리밍 주의사항
        //  、Array.asList()        

        /*
               IteratorSpliterator.forEachRemaining()
        list.stream().forEach(System.out::println);       

        Arrays.asList()

        private static class ArrayList extends AbstractList implements RandomAccess, java.io.Serializable{

        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
            }

        @Override
        public Spliterator spliterator() {
            return Spliterators.spliterator(a, Spliterator.ORDERED);
            }

        }

        public static  Spliterator 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 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

좋은 웹페이지 즐겨찾기