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