3(学習プロセス)を達成根底--streamを学習JAVA8

ストリーム深さ(C)

経験:で、深さ、基になるストリームをストリームを学習する前に。しかし、通常の日常の開発プロセスの過程で学んだこれらのものは、単に使用されていません。ただ、助けに自身がより良い基盤となる施設・ストリームを理解します。もっと自信は非常に右の何かによって決定することができ、それらを使用してください。

技術に焦点:このような環境のこの純粋に技術的な。

代わりに、というのが:5年間の事業開発に焦点を当て、技術が成長しませんでした。

教師は張ロングウェイは、新しい技術を学んでいるの講義を行いました。あなたはこのように感じる場合は、それは非常に効果的で学びます。あなたは、新しい技術を学ぶためにこの方法を使用することができます。

ラムダ式と匿名内部クラスは完全に異なります

ストリームの前に学校が、しかし、かなり十分ではありません。我々はまた、最大使用することを開始から終了までの流れのプロセスを実行することができるようにするプロセスを欠いています。

次は、この目的を達成します

プログラムを開始することができます。

public class LambdaTest {
    //内部类和lambda表达式到底有什么关系
    Runnable r1 = () -> System.out.println(this);

    //匿名内部类 - 标识我生成了一个Runnable的实例 . 是一个类
    Runnable r2 = new Runnable() {
        @Override
        public void run() {
            System.out.println(this);
        }
    };

    public static void main(String[] args) {
        LambdaTest lambdaTest = new LambdaTest();
        Thread t1 = new Thread(lambdaTest.r1);
        t1.start();

        System.out.println("-------------");
        Thread t2 = new Thread(lambdaTest.r2);
        t2.start();
        //请问,输出结果一样吗?
    }
}

結果:

-------------
com.dawa.jdk8.LambdaTest@59a30351   (lambda表达式的结果)
com.dawa.jdk8.LambdaTest$1@2831008d  (匿名内部类的结果)

Process finished with exit code 0

LambdaTest$1これは、クラス名匿名内部クラスです。(匿名内部クラスの名前)

比較すると、ラムダは匿名内部クラスの異なる実装され、そのうち2つがまったく同じではあるが。異なる原理。

結論:

  1. 匿名内部クラスは、新しいスコープを開きます
  2. ラムダは、新しいスコープを開くつもりはありません

デバッグは、別のクラス名匿名内部クラスとラムダ式を見つけるとき、ここで後のために、この知識を普及、


ストリームの実行の流れを引き継ぐためのシステム

public class StreamTest3 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello", "world", "welcome");
        list.stream().map(item->item+"_abc").forEach(System.out::println);
    }
}

(マップ)を達成するために

返却値StatelessOp

@Override
    @SuppressWarnings("unchecked")
    public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
        Objects.requireNonNull(mapper);
        return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
                                     StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
            @Override
            Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
                return new Sink.ChainedReference<P_OUT, R>(sink) {
                    @Override
                    public void accept(P_OUT u) {
                        downstream.accept(mapper.apply(u));
                    }
                };
            }
        };
    }
//StatelessOp类的定义和构造方法
    /**
     * Base class for a stateless intermediate stage of a Stream.
     *
     * @param <E_IN> type of elements in the upstream source
     * @param <E_OUT> type of elements in produced by this stage
     * @since 1.8
     */
abstract static class StatelessOp<E_IN, E_OUT>
            extends ReferencePipeline<E_IN, E_OUT> {
        /**
         * Construct a new Stream by appending a stateless intermediate
         * operation to an existing stream.
         *
         * @param upstream The upstream pipeline stage
         * @param inputShape The stream shape for the upstream pipeline stage
         * @param opFlags Operation flags for the new stage
         */
        StatelessOp(AbstractPipeline<?, E_IN, ?> upstream,
                    StreamShape inputShape,
                    int opFlags) {
            super(upstream, opFlags);
            assert upstream.getOutputShape() == inputShape;
        }

        @Override
        final boolean opIsStateful() {
            return false;
        }
    }

StatelessOp継承ReferencePipeline、そしてReferencePipeline達成Stream

マップ・メソッドが返すので、new StatelessOp<P_OUT, R>リターンに相当しますStream

これは、継承された返されStatelessOpたオブジェクトのサブクラスを。完全な相互運用性の上流と下流の流れ。

参考パイプラインの二重にリンクされたリスト以外の何物でもありません

操作を包装マップChainedReferenceの()メソッドopWrapSink()、包装作業の流れを達成します。ストリームの残りの部分は一緒にワープします

次に一つの要素、および操作方法の残りの部分。

@Override
            Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
                return new Sink.ChainedReference<P_OUT, R>(sink) {
                    @Override
                    public void accept(P_OUT u) {
                        downstream.accept(mapper.apply(u));
                    }
                };
            }
 Sink 类
 * <p>A sink may be in one of two states: an initial state and an active state.
 * It starts out in the initial state; the {@code begin()} method transitions
 * it to the active state, and the {@code end()} method transitions it back into
 * the initial state, where it can be re-used.  Data-accepting methods (such as
 * {@code accept()} are only valid in the active state.
 *

ChainedReference()リンクの参照

    /**
     * Abstract {@code Sink} implementation for creating chains of
     * sinks.  The {@code begin}, {@code end}, and
     * {@code cancellationRequested} methods are wired to chain to the
     * downstream {@code Sink}.  This implementation takes a downstream
     * {@code Sink} of unknown input shape and produces a {@code Sink<T>}.  The
     * implementation of the {@code accept()} method must call the correct
     * {@code accept()} method on the downstream {@code Sink}.
     */
    static abstract class ChainedReference<T, E_OUT> implements Sink<T> {
        protected final Sink<? super E_OUT> downstream;

        public ChainedReference(Sink<? super E_OUT> downstream) {
            this.downstream = Objects.requireNonNull(downstream);
        }

        @Override
        public void begin(long size) {
            downstream.begin(size);
        }

        @Override
        public void end() {
            downstream.end();
        }

        @Override
        public boolean cancellationRequested() {
            return downstream.cancellationRequested();
        }
    }

シンククラスを終了()、及び2つの状態の間()メソッド、開始:アクティブ状態2初期状態

実行前にすべて受け入れる()メソッドは、呼び出しは、実行が完了した後に終了()メソッドを呼び出して、アクティブ状態に、()メソッドでシンクを開始し、初期状態に入ります。

Template Methodパターン:デザインモードに関与します。

opWrapSink()上司が実現します:

シンク動作の結果を受信し、受信したオブジェクト、およびシンクを返し、操作を実行する、及びシンクに結果が提供される渡します。*(入力パラメータとシンクの結果である)
シンクを包むために、正確にこのために動作。

    /**
     * Accepts a {@code Sink} which will receive the results of this operation,
     * and return a {@code Sink} which accepts elements of the input type of
     * this operation and which performs the operation, passing the results to
     * the provided {@code Sink}.
     接受了一个Sink对象,这个对象接受了操作的结果,并且返回了一个Sink,还会执行这个操作,并将这个结果传递给所提供的sink。  *(输入参数才是带结果的sinK)
     正式因为这种操作,才能将sink给包装起来。
     *
     * @apiNote
     * The implementation may use the {@code flags} parameter to optimize the
     * sink wrapping.  For example, if the input is already {@code DISTINCT},
     * the implementation for the {@code Stream#distinct()} method could just
     * return the sink it was passed.
     *
     * @param flags The combined stream and operation flags up to, but not
     *        including, this operation
     
     * @param sink sink to which elements should be sent after processing
     * @return a sink which accepts elements, perform the operation upon
     *         each element, and passes the results (if any) to the provided
     *         {@code Sink}.
     参数本身是用来接收结果的,而不是用返回值来返回结果的。
     */
    abstract Sink<E_IN> opWrapSink(int flags, Sink<E_OUT> sink);
        @Override
        final Sink<E_IN> opWrapSink(int flags, Sink<E_OUT> sink) {
            throw new UnsupportedOperationException();
        }

流量特性:遅延評価と遅延評価。

これらの中間の操作のような他のPEEK()、フィルタ()メソッドを含む()メソッドを、マップ。ジャストはStatelessOpオブジェクトへの復帰を完了しました。

したがって、終端オブジェクトを実行することができる中間StatelessOpに動作戻って、動作が終了されていない、フローは処理されません。

その後、動作を終了します。我々は少し長く追いかけたいです。


forEachの書かれたコード()メソッドが追撃を始めましょう

    // Terminal operations from Stream

    @Override
    public void forEach(Consumer<? super P_OUT> action) {
        evaluate(ForEachOps.makeRef(action, false));
    }

これはmakeRef()メソッド。メソッドForEachOpsクラスと呼ばれています。

ルックForEachOpsクラスのjavadoc

/**
 * Factory for creating instances of {@code TerminalOp} that perform an
 * action for every element of a stream.  Supported variants include unordered
 * traversal (elements are provided to the {@code Consumer} as soon as they are
 * available), and ordered traversal (elements are provided to the
 * {@code Consumer} in encounter order.)
 这是一个工厂,用来创建 TerminalOp 对象,(终止操作。)这个对象会对每一个元素执行一个动作。
 所支持的变化包括:无序的遍历,有序的遍历(按照所提供的的顺序来遍历)。
 *
 * <p>Elements are provided to the {@code Consumer} on whatever thread and
 * whatever order they become available.  For ordered traversals, it is
 * guaranteed that processing an element <em>happens-before</em> processing
 * subsequent elements in the encounter order.
 元素被提供被一个任何可用的Consumer队形。
 处理一个元素,一定是发生在 另外一件事之前 (happens-before)。
也就事 先遇到的元素先处理,后遇到的元素后处理。
 
 *
 * <p>Exceptions occurring as a result of sending an element to the
 * {@code Consumer} will be relayed to the caller and traversal will be
 * prematurely terminated.
 提供了大量的  静态方法。
 *
 * @since 1.8
 */
final class ForEachOps {
    
}

makeRefとして()

   /**
     * Constructs a {@code TerminalOp} that perform an action for every element
     * of a stream.
     *
     * @param action the {@code Consumer} that receives all elements of a
     *        stream
     * @param ordered whether an ordered traversal is requested
     * @param <T> the type of the stream elements
     * @return the {@code TerminalOp} instance
     */
    public static <T> TerminalOp<T, Void> makeRef(Consumer<? super T> action,
                                                  boolean ordered) {
        Objects.requireNonNull(action);
        return new ForEachOp.OfRef<>(action, ordered);
    }

TerminalOp説明

デフォルトでは、シリアル実行です。

/**
 * An operation in a stream pipeline that takes a stream as input and produces
 * a result or side-effect.  A {@code TerminalOp} has an input type and stream
 * shape, and a result type.  A {@code TerminalOp} also has a set of
 * <em>operation flags</em> that describes how the operation processes elements
 * of the stream (such as short-circuiting or respecting encounter order; see
 * {@link StreamOpFlag}).
 流管道中的一个操作。会接受一个流作为输入,  产生的结果,是有副作用的(副作用:你传递了一个引用,你修改了这个引用)。
 一个 TerminalOp 会有一个输入类型,和流的shape 和一个结果类型。
 TerminalOp 还会有一个 如何处理流中的元素  的标识。
 TerminalOp 必须要提供一种 串行的和并行的 实现。
 
 *
 * <p>A {@code TerminalOp} must provide a sequential and parallel implementation
 * of the operation relative to a given stream source and set of intermediate
 * operations.
 *
 * @param <E_IN> the type of input elements
 * @param <R>    the type of the result
 * @since 1.8
 */
interface TerminalOp<E_IN, R> {
        /**
     * Gets the shape of the input type of this operation.
     *
     * @implSpec The default returns {@code StreamShape.REFERENCE}.
     *
     * @return StreamShape of the input type of this operation
     */
    default StreamShape inputShape() { return StreamShape.REFERENCE; }

    /**
     * Gets the stream flags of the operation.  Terminal operations may set a
     * limited subset of the stream flags defined in {@link StreamOpFlag}, and
     * these flags are combined with the previously combined stream and
     * intermediate operation flags for the pipeline.
     *
     * @implSpec The default implementation returns zero.
     *
     * @return the stream flags for this operation
     * @see StreamOpFlag
     */
    default int getOpFlags() { return 0; }

    /**
     * Performs a parallel evaluation of the operation using the specified
     * {@code PipelineHelper}, which describes the upstream intermediate
     * operations.
     *
     * @implSpec The default performs a sequential evaluation of the operation
     * using the specified {@code PipelineHelper}.
     *
     * @param helper the pipeline helper
     * @param spliterator the source spliterator
     * @return the result of the evaluation
     */
    default <P_IN> R evaluateParallel(PipelineHelper<E_IN> helper,
                                      Spliterator<P_IN> spliterator) {
        if (Tripwire.ENABLED)
            Tripwire.trip(getClass(), "{0} triggering TerminalOp.evaluateParallel serial default");
        return evaluateSequential(helper, spliterator);
    }

    /**
     * Performs a sequential evaluation of the operation using the specified
     * {@code PipelineHelper}, which describes the upstream intermediate
     * operations.
     *
     * @param helper the pipeline helper
     * @param spliterator the source spliterator
     * @return the result of the evaluation
     */
    <P_IN> R evaluateSequential(PipelineHelper<E_IN> helper,
                                Spliterator<P_IN> spliterator);
}

終了操作は4つのカテゴリーに実装しました:

1.find

2.match

3.forEachトラバーサル

4.reduce

戻る:forEachの()操作が終了するオブジェクトを返す操作です。

次に:操作対象の終了を実行するために()メソッドを評価します。


    // Terminal evaluation methods

    /**
     * Evaluate the pipeline with a terminal operation to produce a result.
     *
     * @param <R> the type of result
     * @param terminalOp the terminal operation to be applied to the pipeline.
     * @return the result
     */
final <R> R evaluate(TerminalOp<E_OUT, R> terminalOp) {
        assert getOutputShape() == terminalOp.inputShape();
        if (linkedOrConsumed)
            throw new IllegalStateException(MSG_STREAM_LINKED);
        linkedOrConsumed = true;

        return isParallel()
               ? terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags()))
               : terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags()));
    }

PipelineHelper类

情報ストリームの様々なタイプを記述するために使用されます。

/**
 * Helper class for executing <a href="package-summary.html#StreamOps">
 * stream pipelines</a>, capturing all of the information about a stream
 * pipeline (output shape, intermediate operations, stream flags, parallelism,
 * etc) in one place.
 Helper是一个帮助类,用于执行流管道
 包含流管道的所有信息:源数据。输出类型,操作,流标识,并行标记等。
 
 *
 * <p>
 * A {@code PipelineHelper} describes the initial segment of a stream pipeline,
 * including its source, intermediate operations, and may additionally
 * incorporate information about the terminal (or stateful) operation which
 * follows the last intermediate operation described by this
 * {@code PipelineHelper}. The {@code PipelineHelper} is passed to the
 * {@link TerminalOp#evaluateParallel(PipelineHelper, java.util.Spliterator)},
 * {@link TerminalOp#evaluateSequential(PipelineHelper, java.util.Spliterator)},
 * and {@link AbstractPipeline#opEvaluateParallel(PipelineHelper, java.util.Spliterator,
 * java.util.function.IntFunction)}, methods, which can use the
 * {@code PipelineHelper} to access information about the pipeline such as
 * head shape, stream flags, and size, and use the helper methods
 * such as {@link #wrapAndCopyInto(Sink, Spliterator)},
 * {@link #copyInto(Sink, Spliterator)}, and {@link #wrapSink(Sink)} to execute
 * pipeline operations..
 一个流管道的最初的分块,包含源,中间操作和增加的操作。等
 
 PipelineHelper会被传递给。。。。 方法, 就可以通过PipelineHelper来访问管道的各种信息。
 
 *
 * @param <P_OUT> type of output elements from the pipeline
 * @since 1.8
 */
abstract class PipelineHelper<P_OUT> {
    ...
}

PipelineHelperクラスメソッド:wrapAndCopyInto()

   /**
     * Applies the pipeline stages described by this {@code PipelineHelper} to
     * the provided {@code Spliterator} and send the results to the provided
     * {@code Sink}.
     将调用了这个方法的pipeline所描述的管道的各个阶段,同时 应用到Spliterator和发送给Sink对象
     *
     * @implSpec
     * The implementation behaves as if:
     * <pre>{@code
     *     intoWrapped(wrapSink(sink), spliterator);
     * }</pre>
     *
     * @param sink the {@code Sink} to receive the results
     * @param spliterator the spliterator describing the source input to process
     */
    abstract<P_IN, S extends Sink<P_OUT>> S wrapAndCopyInto(S sink, Spliterator<P_IN> spliterator);

具体的な実現wrapAndCopyInto:

    @Override
    final <P_IN, S extends Sink<E_OUT>> S wrapAndCopyInto(S sink, Spliterator<P_IN> spliterator) {
        copyInto(wrapSink(Objects.requireNonNull(sink)), spliterator);
        return sink;
    }

()メソッドでwrapSinkシンク

    /**
     * Takes a {@code Sink} that accepts elements of the output type of the
     * {@code PipelineHelper}, and wrap it with a {@code Sink} that accepts
     * elements of the input type and implements all the intermediate operations
     * described by this {@code PipelineHelper}, delivering the result into the
     * provided {@code Sink}.
     接受了一个Sink, Sink接受了PipelineHelper的所有输出类型。
     
     *
     * @param sink the {@code Sink} to receive the results
     * @return a {@code Sink} that implements the pipeline stages and sends
     *         results to the provided {@code Sink}
     */
    abstract<P_IN> Sink<P_IN> wrapSink(Sink<P_OUT> sink);

wrapSink()メソッドは、具体(複数のストリームのための操作の完全なシリーズ。)

    @Override
    @SuppressWarnings("unchecked")
    final <P_IN> Sink<P_IN> wrapSink(Sink<E_OUT> sink) {
        Objects.requireNonNull(sink);

        //根据depth判断是否有中间操作。 从后往前的去走。
        for ( @SuppressWarnings("rawtypes") AbstractPipeline p=AbstractPipeline.this; p.depth > 0; p=p.previousStage) {
            sink = p.opWrapSink(p.previousStage.combinedFlags, sink);
        }
        return (Sink<P_IN>) sink;
    }

wrapSink()


自己要約:実行フローの流れ。

データソース - 中間動作 - 中間動作 - 終了操作

シリーズ1.すべての操作。(中間動作および終了動作)

2.エレメンタリストリーム、すべての操作が含まれて実行される1つずつをしてみましょう。

方法の核心:でCOPYINTO():spliterator.forEachRemaining(wrappedSink);ステップの//最も核心

 @Override
    final <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) {
        Objects.requireNonNull(wrappedSink);

        if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) {
            wrappedSink.begin(spliterator.getExactSizeIfKnown());
            spliterator.forEachRemaining(wrappedSink); //最最核心的一步
            wrappedSink.end();
        }
        else {
            copyIntoWithCancel(wrappedSink, spliterator);
        }
    }

wrappedSink:すべての中間の操作は、オブジェクトは、このシンクをカプセル化

spliterator:ソース・データ - 、それはシンクオブジェクト封入オーバー操作を実行するたびにforEachRemainingトラバーサルを行います。

上記(ソースコードの解析を介して)静的解析であります

動的解析による自己(プログラムのデバッグ分析)


トンの話で再びコードをデバッグします。

public class StreamTest3 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello", "world", "welcome");
//        list.stream().map(item->item+"_abc").forEach(System.out::println);

        Stream<String> stream = list.stream(); 
        System.out.println("1");//断点
        Stream<String> stream1 = stream.map(item -> item + "_abc");
        System.out.println("2");//断点
        stream1.forEach(System.out::println);
    }
}

おすすめ

転載: www.cnblogs.com/bigbaby/p/12164699.html