8 Kasım 2022 Salı

Stream Arayüzü Neden Lazy

Giriş
Bir çok stream metodu StatelesOp nesnesi döndürür. Şeklen şöyle

Stream metodlarının gerçekleştirimi ReferencePipeline sınıf içinde. ReferencePipeline da aslında kalıtım sebebiyle bir Stream nesnesi.

Bu sınıfın map metoduna bakalım. Kod şöyle. Yeni bir StatelessOp döndürüyor . StatelessOp sınıfı abstract olduğu için davranışını onWrapSink() ile belirterek yeni bir ReferencePipeline yani Stream oluşturdu
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, <- Pass upstream
                                 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)); <- Call next stream
        }
      };
    }
  };
}
StatelessOp constructor şöyle. Burada ilk parametrenin isminin upstream olduğu görülebilir.
StatelessOp(AbstractPipeline<?, E_IN, ?> upstream,
            StreamShape inputShape,
            int opFlags) {
  super(upstream, opFlags);
  assert upstream.getOutputShape() == inputShape;
}
super() ile çağrılam kod şöyle
ReferencePipeline(AbstractPipeline<?, P_IN, ?> upstream, int opFlags) {
  super(upstream, opFlags);
}
ve tekrar super ile çağrılam kod şöyle. Burada upstream'in ismi birden previousStage oldu. Yani her stream arayüzünün sağladığı her metod çağrısı aynı zamanda bir stage olarak düşünülüyor.
AbstractPipeline(AbstractPipeline<?, E_IN, ?> previousStage, int opFlags) {
  if (previousStage.linkedOrConsumed)
    throw new IllegalStateException(MSG_STREAM_LINKED);
  previousStage.linkedOrConsumed = true;
  previousStage.nextStage = this;

  this.previousStage = previousStage;
  this.sourceOrOpFlags = opFlags & StreamOpFlag.OP_MASK;
  this.combinedFlags = StreamOpFlag.combineOpFlags(opFlags, previousStage.combinedFlags);
  this.sourceStage = previousStage.sourceStage;
  if (opIsStateful())
    sourceStage.sourceAnyStateful = true;
  this.depth = previousStage.depth + 1;
}
Elimizde şöyle bir kod olsun
Stream<Integer> integerStream = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2))
  .stream().
  map(Scratch::multiply);
Debugger'daki object'ler şöyle
//sourceStage yerine source
//nextStage yerine sink diyelim

//Pipeline nesnesi. sink null, source @839 
integerStream = ReferencePipeline$3@836
  mapper = Scratch$lambda@838
  sourceStage = ReferencePipeline$Head@839
  previousStage = ReferencePipeline$Head@839
  nextStage = null
  sourceSplitIterator = null;
  sourceSupplier = null;

  //source kendisi sink @836, 
  sourceStage = ReferencePipeline$Head@839
    sourceStage = ReferencePipeline$Head@839
    previousStage = null;
    nextStage = ReferencePipeline$3@836
    sourceSplitIterator = SplitIteratos$ArraySpliterator@840;
    sourceSupplier = null

     //source @839, sink null
      nextStage = ReferencePipeline$3@836
        mapper = Scratch$lambda@838
        sourceStage = ReferencePipeline$Head@839
        previousStage = ReferencePipeline$Head@839 
        nextStage = null
        sourceSplitIterator = null;







Hiç yorum yok:

Yorum Gönder