1 /*
2  * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package java.util.stream;
26 
27 import java.util.LongSummaryStatistics;
28 import java.util.Objects;
29 import java.util.OptionalDouble;
30 import java.util.OptionalLong;
31 import java.util.PrimitiveIterator;
32 import java.util.Spliterator;
33 import java.util.Spliterators;
34 import java.util.function.BiConsumer;
35 import java.util.function.BinaryOperator;
36 import java.util.function.IntFunction;
37 import java.util.function.LongBinaryOperator;
38 import java.util.function.LongConsumer;
39 import java.util.function.LongFunction;
40 import java.util.function.LongPredicate;
41 import java.util.function.LongToDoubleFunction;
42 import java.util.function.LongToIntFunction;
43 import java.util.function.LongUnaryOperator;
44 import java.util.function.ObjLongConsumer;
45 import java.util.function.Supplier;
46 
47 /**
48  * Abstract base class for an intermediate pipeline stage or pipeline source
49  * stage implementing whose elements are of type {@code long}.
50  *
51  * @param <E_IN> type of elements in the upstream source
52  * @since 1.8
53  * @hide Visible for CTS testing only (OpenJDK8 tests).
54  */
55 // Android-changed: Made public for CTS tests only.
56 public abstract class LongPipeline<E_IN>
57         extends AbstractPipeline<E_IN, Long, LongStream>
58         implements LongStream {
59 
60     /**
61      * Constructor for the head of a stream pipeline.
62      *
63      * @param source {@code Supplier<Spliterator>} describing the stream source
64      * @param sourceFlags the source flags for the stream source, described in
65      *        {@link StreamOpFlag}
66      * @param parallel {@code true} if the pipeline is parallel
67      */
LongPipeline(Supplier<? extends Spliterator<Long>> source, int sourceFlags, boolean parallel)68     LongPipeline(Supplier<? extends Spliterator<Long>> source,
69                  int sourceFlags, boolean parallel) {
70         super(source, sourceFlags, parallel);
71     }
72 
73     /**
74      * Constructor for the head of a stream pipeline.
75      *
76      * @param source {@code Spliterator} describing the stream source
77      * @param sourceFlags the source flags for the stream source, described in
78      *        {@link StreamOpFlag}
79      * @param parallel {@code true} if the pipeline is parallel
80      */
LongPipeline(Spliterator<Long> source, int sourceFlags, boolean parallel)81     LongPipeline(Spliterator<Long> source,
82                  int sourceFlags, boolean parallel) {
83         super(source, sourceFlags, parallel);
84     }
85 
86     /**
87      * Constructor for appending an intermediate operation onto an existing pipeline.
88      *
89      * @param upstream the upstream element source.
90      * @param opFlags the operation flags
91      */
LongPipeline(AbstractPipeline<?, E_IN, ?> upstream, int opFlags)92     LongPipeline(AbstractPipeline<?, E_IN, ?> upstream, int opFlags) {
93         super(upstream, opFlags);
94     }
95 
96     /**
97      * Adapt a {@code Sink<Long> to an {@code LongConsumer}, ideally simply
98      * by casting.
99      */
adapt(Sink<Long> sink)100     private static LongConsumer adapt(Sink<Long> sink) {
101         if (sink instanceof LongConsumer) {
102             return (LongConsumer) sink;
103         } else {
104             if (Tripwire.ENABLED)
105                 Tripwire.trip(AbstractPipeline.class,
106                               "using LongStream.adapt(Sink<Long> s)");
107             return sink::accept;
108         }
109     }
110 
111     /**
112      * Adapt a {@code Spliterator<Long>} to a {@code Spliterator.OfLong}.
113      *
114      * @implNote
115      * The implementation attempts to cast to a Spliterator.OfLong, and throws
116      * an exception if this cast is not possible.
117      */
adapt(Spliterator<Long> s)118     private static Spliterator.OfLong adapt(Spliterator<Long> s) {
119         if (s instanceof Spliterator.OfLong) {
120             return (Spliterator.OfLong) s;
121         } else {
122             if (Tripwire.ENABLED)
123                 Tripwire.trip(AbstractPipeline.class,
124                               "using LongStream.adapt(Spliterator<Long> s)");
125             throw new UnsupportedOperationException("LongStream.adapt(Spliterator<Long> s)");
126         }
127     }
128 
129 
130     // Shape-specific methods
131 
132     @Override
133     // Android-changed: Make public, to match the method it's overriding.
getOutputShape()134     public final StreamShape getOutputShape() {
135         return StreamShape.LONG_VALUE;
136     }
137 
138     @Override
139     // Android-changed: Make public, to match the method it's overriding.
evaluateToNode(PipelineHelper<Long> helper, Spliterator<P_IN> spliterator, boolean flattenTree, IntFunction<Long[]> generator)140     public final <P_IN> Node<Long> evaluateToNode(PipelineHelper<Long> helper,
141                                            Spliterator<P_IN> spliterator,
142                                            boolean flattenTree,
143                                            IntFunction<Long[]> generator) {
144         return Nodes.collectLong(helper, spliterator, flattenTree);
145     }
146 
147     @Override
148     // Android-changed: Make public, to match the method it's overriding.
wrap(PipelineHelper<Long> ph, Supplier<Spliterator<P_IN>> supplier, boolean isParallel)149     public final <P_IN> Spliterator<Long> wrap(PipelineHelper<Long> ph,
150                                         Supplier<Spliterator<P_IN>> supplier,
151                                         boolean isParallel) {
152         return new StreamSpliterators.LongWrappingSpliterator<>(ph, supplier, isParallel);
153     }
154 
155     @Override
156     @SuppressWarnings("unchecked")
157     // Android-changed: Make public, to match the method it's overriding.
lazySpliterator(Supplier<? extends Spliterator<Long>> supplier)158     public final Spliterator.OfLong lazySpliterator(Supplier<? extends Spliterator<Long>> supplier) {
159         return new StreamSpliterators.DelegatingSpliterator.OfLong((Supplier<Spliterator.OfLong>) supplier);
160     }
161 
162     @Override
163     // Android-changed: Make public, to match the method it's overriding.
forEachWithCancel(Spliterator<Long> spliterator, Sink<Long> sink)164     public final boolean forEachWithCancel(Spliterator<Long> spliterator, Sink<Long> sink) {
165         Spliterator.OfLong spl = adapt(spliterator);
166         LongConsumer adaptedSink =  adapt(sink);
167         boolean cancelled;
168         do { } while (!(cancelled = sink.cancellationRequested()) && spl.tryAdvance(adaptedSink));
169         return cancelled;
170     }
171 
172     @Override
173     // Android-changed: Make public, to match the method it's overriding.
makeNodeBuilder(long exactSizeIfKnown, IntFunction<Long[]> generator)174     public final Node.Builder<Long> makeNodeBuilder(long exactSizeIfKnown, IntFunction<Long[]> generator) {
175         return Nodes.longBuilder(exactSizeIfKnown);
176     }
177 
mapToObj(LongFunction<? extends U> mapper, int opFlags)178     private <U> Stream<U> mapToObj(LongFunction<? extends U> mapper, int opFlags) {
179         return new ReferencePipeline.StatelessOp<Long, U>(this, StreamShape.LONG_VALUE, opFlags) {
180             @Override
181             // Android-changed: Make public, to match the method it's overriding.
182             public Sink<Long> opWrapSink(int flags, Sink<U> sink) {
183                 return new Sink.ChainedLong<U>(sink) {
184                     @Override
185                     public void accept(long t) {
186                         downstream.accept(mapper.apply(t));
187                     }
188                 };
189             }
190         };
191     }
192 
193     // LongStream
194 
195     @Override
196     public final PrimitiveIterator.OfLong iterator() {
197         return Spliterators.iterator(spliterator());
198     }
199 
200     @Override
201     public final Spliterator.OfLong spliterator() {
202         return adapt(super.spliterator());
203     }
204 
205     // Stateless intermediate ops from LongStream
206 
207     @Override
208     public final DoubleStream asDoubleStream() {
209         return new DoublePipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE, StreamOpFlag.NOT_DISTINCT) {
210             @Override
211             // Android-changed: Make public, to match the method it's overriding.
212             public Sink<Long> opWrapSink(int flags, Sink<Double> sink) {
213                 return new Sink.ChainedLong<Double>(sink) {
214                     @Override
215                     public void accept(long t) {
216                         downstream.accept((double) t);
217                     }
218                 };
219             }
220         };
221     }
222 
223     @Override
224     public final Stream<Long> boxed() {
225         return mapToObj(Long::valueOf, 0);
226     }
227 
228     @Override
229     public final LongStream map(LongUnaryOperator mapper) {
230         Objects.requireNonNull(mapper);
231         return new StatelessOp<Long>(this, StreamShape.LONG_VALUE,
232                                      StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
233             @Override
234             // Android-changed: Make public, to match the method it's overriding.
235             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
236                 return new Sink.ChainedLong<Long>(sink) {
237                     @Override
238                     public void accept(long t) {
239                         downstream.accept(mapper.applyAsLong(t));
240                     }
241                 };
242             }
243         };
244     }
245 
246     @Override
247     public final <U> Stream<U> mapToObj(LongFunction<? extends U> mapper) {
248         Objects.requireNonNull(mapper);
249         return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT);
250     }
251 
252     @Override
253     public final IntStream mapToInt(LongToIntFunction mapper) {
254         Objects.requireNonNull(mapper);
255         return new IntPipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE,
256                                                  StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
257             @Override
258             // Android-changed: Make public, to match the method it's overriding.
259             public Sink<Long> opWrapSink(int flags, Sink<Integer> sink) {
260                 return new Sink.ChainedLong<Integer>(sink) {
261                     @Override
262                     public void accept(long t) {
263                         downstream.accept(mapper.applyAsInt(t));
264                     }
265                 };
266             }
267         };
268     }
269 
270     @Override
271     public final DoubleStream mapToDouble(LongToDoubleFunction mapper) {
272         Objects.requireNonNull(mapper);
273         return new DoublePipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE,
274                                                     StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
275             @Override
276             // Android-changed: Make public, to match the method it's overriding.
277             public Sink<Long> opWrapSink(int flags, Sink<Double> sink) {
278                 return new Sink.ChainedLong<Double>(sink) {
279                     @Override
280                     public void accept(long t) {
281                         downstream.accept(mapper.applyAsDouble(t));
282                     }
283                 };
284             }
285         };
286     }
287 
288     @Override
289     public final LongStream flatMap(LongFunction<? extends LongStream> mapper) {
290         Objects.requireNonNull(mapper);
291         return new StatelessOp<Long>(this, StreamShape.LONG_VALUE,
292                                      StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
293             @Override
294             // Android-changed: Make public, to match the method it's overriding.
295             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
296                 return new Sink.ChainedLong<Long>(sink) {
297                     // true if cancellationRequested() has been called
298                     boolean cancellationRequestedCalled;
299 
300                     // cache the consumer to avoid creation on every accepted element
301                     LongConsumer downstreamAsLong = downstream::accept;
302 
303                     @Override
304                     public void begin(long size) {
305                         downstream.begin(-1);
306                     }
307 
308                     @Override
309                     public void accept(long t) {
310                         try (LongStream result = mapper.apply(t)) {
311                             if (result != null) {
312                                 if (!cancellationRequestedCalled) {
313                                     result.sequential().forEach(downstreamAsLong);
314                                 }
315                                 else {
316                                     var s = result.sequential().spliterator();
317                                     do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstreamAsLong));
318                                 }
319                             }
320                         }
321                     }
322 
323                     @Override
324                     public boolean cancellationRequested() {
325                         // If this method is called then an operation within the stream
326                         // pipeline is short-circuiting (see AbstractPipeline.copyInto).
327                         // Note that we cannot differentiate between an upstream or
328                         // downstream operation
329                         cancellationRequestedCalled = true;
330                         return downstream.cancellationRequested();
331                     }
332                 };
333             }
334         };
335     }
336 
337     @Override
338     public final LongStream mapMulti(LongMapMultiConsumer mapper) {
339         Objects.requireNonNull(mapper);
340         return new LongPipeline.StatelessOp<>(this, StreamShape.LONG_VALUE,
341                 StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
342             @Override
343             // Android-changed: Make public, to match the method it's overriding.
344             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
345                 return new Sink.ChainedLong<>(sink) {
346 
347                     @Override
348                     public void begin(long size) {
349                         downstream.begin(-1);
350                     }
351 
352                     @Override
353                     @SuppressWarnings("unchecked")
354                     public void accept(long t) {
355                         mapper.accept(t, (LongConsumer) downstream);
356                     }
357                 };
358             }
359         };
360     }
361 
362     @Override
363     public LongStream unordered() {
364         if (!isOrdered())
365             return this;
366         return new StatelessOp<Long>(this, StreamShape.LONG_VALUE, StreamOpFlag.NOT_ORDERED) {
367             @Override
368             // Android-changed: Make public, to match the method it's overriding.
369             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
370                 return sink;
371             }
372         };
373     }
374 
375     @Override
376     public final LongStream filter(LongPredicate predicate) {
377         Objects.requireNonNull(predicate);
378         return new StatelessOp<Long>(this, StreamShape.LONG_VALUE,
379                                      StreamOpFlag.NOT_SIZED) {
380             @Override
381             // Android-changed: Make public, to match the method it's overriding.
382             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
383                 return new Sink.ChainedLong<Long>(sink) {
384                     @Override
385                     public void begin(long size) {
386                         downstream.begin(-1);
387                     }
388 
389                     @Override
390                     public void accept(long t) {
391                         if (predicate.test(t))
392                             downstream.accept(t);
393                     }
394                 };
395             }
396         };
397     }
398 
399     @Override
400     public final LongStream peek(LongConsumer action) {
401         Objects.requireNonNull(action);
402         return new StatelessOp<Long>(this, StreamShape.LONG_VALUE,
403                                      0) {
404             @Override
405             // Android-changed: Make public, to match the method it's overriding.
406             public Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
407                 return new Sink.ChainedLong<Long>(sink) {
408                     @Override
409                     public void accept(long t) {
410                         action.accept(t);
411                         downstream.accept(t);
412                     }
413                 };
414             }
415         };
416     }
417 
418     // Stateful intermediate ops from LongStream
419 
420     @Override
421     public final LongStream limit(long maxSize) {
422         if (maxSize < 0)
423             throw new IllegalArgumentException(Long.toString(maxSize));
424         return SliceOps.makeLong(this, 0, maxSize);
425     }
426 
427     @Override
428     public final LongStream skip(long n) {
429         if (n < 0)
430             throw new IllegalArgumentException(Long.toString(n));
431         if (n == 0)
432             return this;
433         else
434             return SliceOps.makeLong(this, n, -1);
435     }
436 
437     @Override
438     public final LongStream takeWhile(LongPredicate predicate) {
439         return WhileOps.makeTakeWhileLong(this, predicate);
440     }
441 
442     @Override
443     public final LongStream dropWhile(LongPredicate predicate) {
444         return WhileOps.makeDropWhileLong(this, predicate);
445     }
446 
447     @Override
448     public final LongStream sorted() {
449         return SortedOps.makeLong(this);
450     }
451 
452     @Override
453     public final LongStream distinct() {
454         // While functional and quick to implement, this approach is not very efficient.
455         // An efficient version requires a long-specific map/set implementation.
456         return boxed().distinct().mapToLong(i -> (long) i);
457     }
458 
459     // Terminal ops from LongStream
460 
461     @Override
462     public void forEach(LongConsumer action) {
463         evaluate(ForEachOps.makeLong(action, false));
464     }
465 
466     @Override
467     public void forEachOrdered(LongConsumer action) {
468         evaluate(ForEachOps.makeLong(action, true));
469     }
470 
471     @Override
472     public final long sum() {
473         // use better algorithm to compensate for intermediate overflow?
474         return reduce(0, Long::sum);
475     }
476 
477     @Override
478     public final OptionalLong min() {
479         return reduce(Math::min);
480     }
481 
482     @Override
483     public final OptionalLong max() {
484         return reduce(Math::max);
485     }
486 
487     @Override
488     public final OptionalDouble average() {
489         long[] avg = collect(() -> new long[2],
490                              (ll, i) -> {
491                                  ll[0]++;
492                                  ll[1] += i;
493                              },
494                              (ll, rr) -> {
495                                  ll[0] += rr[0];
496                                  ll[1] += rr[1];
497                              });
498         return avg[0] > 0
499                ? OptionalDouble.of((double) avg[1] / avg[0])
500                : OptionalDouble.empty();
501     }
502 
503     @Override
504     public final long count() {
505         return evaluate(ReduceOps.makeLongCounting());
506     }
507 
508     @Override
509     public final LongSummaryStatistics summaryStatistics() {
510         return collect(LongSummaryStatistics::new, LongSummaryStatistics::accept,
511                        LongSummaryStatistics::combine);
512     }
513 
514     @Override
515     public final long reduce(long identity, LongBinaryOperator op) {
516         return evaluate(ReduceOps.makeLong(identity, op));
517     }
518 
519     @Override
520     public final OptionalLong reduce(LongBinaryOperator op) {
521         return evaluate(ReduceOps.makeLong(op));
522     }
523 
524     @Override
525     public final <R> R collect(Supplier<R> supplier,
526                                ObjLongConsumer<R> accumulator,
527                                BiConsumer<R, R> combiner) {
528         Objects.requireNonNull(combiner);
529         BinaryOperator<R> operator = (left, right) -> {
530             combiner.accept(left, right);
531             return left;
532         };
533         return evaluate(ReduceOps.makeLong(supplier, accumulator, operator));
534     }
535 
536     @Override
537     public final boolean anyMatch(LongPredicate predicate) {
538         return evaluate(MatchOps.makeLong(predicate, MatchOps.MatchKind.ANY));
539     }
540 
541     @Override
542     public final boolean allMatch(LongPredicate predicate) {
543         return evaluate(MatchOps.makeLong(predicate, MatchOps.MatchKind.ALL));
544     }
545 
546     @Override
547     public final boolean noneMatch(LongPredicate predicate) {
548         return evaluate(MatchOps.makeLong(predicate, MatchOps.MatchKind.NONE));
549     }
550 
551     @Override
552     public final OptionalLong findFirst() {
553         return evaluate(FindOps.makeLong(true));
554     }
555 
556     @Override
557     public final OptionalLong findAny() {
558         return evaluate(FindOps.makeLong(false));
559     }
560 
561     @Override
562     public final long[] toArray() {
563         return Nodes.flattenLong((Node.OfLong) evaluateToArrayNode(Long[]::new))
564                 .asPrimitiveArray();
565     }
566 
567 
568     //
569 
570     /**
571      * Source stage of a LongPipeline.
572      *
573      * @param <E_IN> type of elements in the upstream source
574      * @since 1.8
575      * @hide Made public for CTS tests only (OpenJDK 8 streams tests).
576      */
577     // Android-changed: Made public for CTS tests only.
578     public static class Head<E_IN> extends LongPipeline<E_IN> {
579         /**
580          * Constructor for the source stage of a LongStream.
581          *
582          * @param source {@code Supplier<Spliterator>} describing the stream
583          *               source
584          * @param sourceFlags the source flags for the stream source, described
585          *                    in {@link StreamOpFlag}
586          * @param parallel {@code true} if the pipeline is parallel
587          */
588         // Android-changed: Made public for CTS tests only.
589         public Head(Supplier<? extends Spliterator<Long>> source,
590              int sourceFlags, boolean parallel) {
591             super(source, sourceFlags, parallel);
592         }
593 
594         /**
595          * Constructor for the source stage of a LongStream.
596          *
597          * @param source {@code Spliterator} describing the stream source
598          * @param sourceFlags the source flags for the stream source, described
599          *                    in {@link StreamOpFlag}
600          * @param parallel {@code true} if the pipeline is parallel
601          */
602         // Android-changed: Made public for CTS tests only.
603         public Head(Spliterator<Long> source,
604              int sourceFlags, boolean parallel) {
605             super(source, sourceFlags, parallel);
606         }
607 
608         @Override
609         // Android-changed: Make public, to match the method it's overriding.
610         public final boolean opIsStateful() {
611             throw new UnsupportedOperationException();
612         }
613 
614         @Override
615         // Android-changed: Make public, to match the method it's overriding.
616         public final Sink<E_IN> opWrapSink(int flags, Sink<Long> sink) {
617             throw new UnsupportedOperationException();
618         }
619 
620         // Optimized sequential terminal operations for the head of the pipeline
621 
622         @Override
623         public void forEach(LongConsumer action) {
624             if (!isParallel()) {
625                 adapt(sourceStageSpliterator()).forEachRemaining(action);
626             } else {
627                 super.forEach(action);
628             }
629         }
630 
631         @Override
632         public void forEachOrdered(LongConsumer action) {
633             if (!isParallel()) {
634                 adapt(sourceStageSpliterator()).forEachRemaining(action);
635             } else {
636                 super.forEachOrdered(action);
637             }
638         }
639     }
640 
641     /** Base class for a stateless intermediate stage of a LongStream.
642      *
643      * @param <E_IN> type of elements in the upstream source
644      * @since 1.8
645      * @hide Visible for CTS testing only (OpenJDK8 tests).
646      */
647     // Android-changed: Made public for CTS tests only.
648     public abstract static class StatelessOp<E_IN> extends LongPipeline<E_IN> {
649         /**
650          * Construct a new LongStream by appending a stateless intermediate
651          * operation to an existing stream.
652          * @param upstream The upstream pipeline stage
653          * @param inputShape The stream shape for the upstream pipeline stage
654          * @param opFlags Operation flags for the new stage
655          */
656         // Android-changed: Made public for CTS tests only.
657         public StatelessOp(AbstractPipeline<?, E_IN, ?> upstream,
658                     StreamShape inputShape,
659                     int opFlags) {
660             super(upstream, opFlags);
661             assert upstream.getOutputShape() == inputShape;
662         }
663 
664         @Override
665         // Android-changed: Make public, to match the method it's overriding.
666         public final boolean opIsStateful() {
667             return false;
668         }
669     }
670 
671     /**
672      * Base class for a stateful intermediate stage of a LongStream.
673      *
674      * @param <E_IN> type of elements in the upstream source
675      * @since 1.8
676      * @hide Visible for CTS testing only (OpenJDK8 tests).
677      */
678     // Android-changed: Made public for CTS tests only.
679     public abstract static class StatefulOp<E_IN> extends LongPipeline<E_IN> {
680         /**
681          * Construct a new LongStream by appending a stateful intermediate
682          * operation to an existing stream.
683          * @param upstream The upstream pipeline stage
684          * @param inputShape The stream shape for the upstream pipeline stage
685          * @param opFlags Operation flags for the new stage
686          * @hide Visible for CTS testing only (OpenJDK8 tests).
687          */
688         // Android-changed: Made public for CTS tests only.
689         public StatefulOp(AbstractPipeline<?, E_IN, ?> upstream,
690                    StreamShape inputShape,
691                    int opFlags) {
692             super(upstream, opFlags);
693             assert upstream.getOutputShape() == inputShape;
694         }
695 
696         @Override
697         // Android-changed: Make public, to match the method it's overriding.
698         public final boolean opIsStateful() {
699             return true;
700         }
701 
702         @Override
703         // Android-changed: Make public, to match the method it's overriding.
704         public abstract <P_IN> Node<Long> opEvaluateParallel(PipelineHelper<Long> helper,
705                                                       Spliterator<P_IN> spliterator,
706                                                       IntFunction<Long[]> generator);
707     }
708 }
709