
scala.compat.java8.collectionImpl.Stepper.scala Maven / Gradle / Ivy
The newest version!
package scala.compat.java8.collectionImpl
import java.util.Spliterator
/** A Stepper is a specialized collection that can step through its
* contents once. It provides the same test-and-get methods as
* does `Iterator`, named `hasStep` and `nextStep` so they can
* coexist with iterator methods. However, like `Spliterator`,
* steppers provide a `tryStep` method to call a closure if another
* element exists, a `substep()` method to split into pieces, and
* `characteristics` and size-reporting methods that
* implement the subdivision and report what is known about the remaining
* size of the `Stepper`. `Stepper` thus naturally implements both
* `Iterator` and `Spliterator`.
*
* A `Stepper` can present itself as a Spliterator via the `spliterator`
* method, or as a Scala Iterator via the `iterator` method. The `Stepper`
* trait is compatible with both `Spliterator` and Java's generic and
* primitive iterators, so a `Stepper` may already be one or both.
*
* Subtraits `NextStepper` and `TryStepper` fill in the basic capability
* by either implementing `tryStep` in terms of `hasStep` and `nextStep`,
* or vice versa.
*
* Subtraits `AnyStepper`, `DoubleStepper`, `IntStepper`, and `LongStepper`
* implement both the `Stepper` trait and the corresponding Java
* `Spliterator` and `Iterator`/`PrimitiveIterator`.
*
* Example:
* {{{
* val s = Stepper.of(Vector(1,2,3,4))
* if (s.hasStep) println(s.nextStep) // Prints 1
* println(s.tryStep(i => println(i*i))) // Prints 4, then true
* s.substep.foreach(println) // Prints 3
* println(s.count(_ > 3)) // Prints 4
* println(s.hasStep) // Prints `false`
* }}}
*/
trait Stepper[@specialized(Double, Int, Long) A] extends StepperLike[A, Stepper[A]] {
/** Drains the contents of this stepper into an `Accumulator` or specialized variant thereof as appropriate.
* This is a terminal operation.
*
* Note: accumulation will occur sequentially. To accumulate in parallel, use a `Stream` (i.e. `.parStream.accumulate`).
*/
def accumulate[Acc <: AccumulatorLike[A, Acc]](implicit accer: scala.compat.java8.converterImpl.AccumulatesFromStepper[A, Acc]) = accer(this)
}
/** An (optional) marker trait that indicates that a `Stepper` can call `substep` with
* at worst O(log N) time and space complexity, and that the division is likely to
* be reasonably even.
*/
trait EfficientSubstep {}
/** Provides functionality for Stepper while keeping track of a more precise type of the collection.
*/
trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self: CC =>
/** Characteristics are bit flags that indicate runtime characteristics of this Stepper.
*
* - `Distinct` means that no duplicates exist
* - `Immutable` means that the underlying collection is guaranteed not to change during traversal
* - `NonNull` means that no nulls will be returned during traversal
* - `Sized` means that the collection knows its exact size
* - `SubSized` means that sub-Steppers created with `substep()` will also know their own size. `SubSized` steppers must also be `Sized`.
*
* The Java flags `CONCURRENT` and `SORTED` are not supported; modification of a concurrency-aware underlying collection is not
* guaranteed to be any safer than modification of any generic mutable collection, and if the underlying collection is ordered by
* virtue of sorting, `Stepper` will not keep track of that fact.
*/
def characteristics: Int
/** Returns the size of the collection, if known exactly, or `-1` if not. */
def knownSize: Long
/** `true` if there are more elements to step through, `false` if not. */
def hasStep: Boolean
/** The next element traversed by this Stepper.
* `nextStep()` throws an exception if no elements exist, so check `hasStep` immediately prior
* to calling. Note that `tryStep` also consumes an element, so the result of `hasStep` will
* be invalid after `tryStep` is called.
*/
def nextStep(): A
/** If another element exists, apply `f` to it and return `true`; otherwise, return `false`. */
def tryStep(f: A => Unit): Boolean
/** Attempt to split this `Stepper` in half, with the new (returned) copy taking the first half
* of the collection, and this one advancing to cover the second half. If subdivision is not
* possible or not advisable, `substep()` will return `null`.
*/
def substep(): CC
/** Warns this `Stepper` that it is likely to be used in a parallel context (used for efficiency only) */
def anticipateParallelism: this.type = this
////
// Terminal operations (do not produce another Stepper)
////
/** Consumes all remaining elements in this `Stepper` and counts how many there are.
* This is a terminal operation, though if `knownSize` is non-negative, it won't actually
* iterate over the elements.
*/
def count(): Long = knownSize match {
case x if x < 0 => var n = 0L; while (hasStep) { nextStep; n += 1 }; n
case x => x
}
/** Consumes all remaining elements in this `Stepper` and counts how many satisfy condition `p`.
* This is a terminal operation.
*/
def count(p: A => Boolean): Long = { var n = 0L; while (hasStep) { if (p(nextStep)) n += 1 }; n }
/** Searches for an element that satisfies condition `p`. If none are found, it returns `false`.
* This is a terminal operation.
*/
def exists(p: A => Boolean): Boolean = { while(hasStep) { if (p(nextStep)) return true }; false }
/** Searches for an element that satisifes condition `p`, returning it wrapped in `Some` if one is found, or `None` otherwise.
* This is a terminal operation.
*/
def find(p: A => Boolean): Option[A] = { while (hasStep) { val a = nextStep; if (p(a)) return Some(a) }; None }
/** Repeatedly applies `op` to propagate an initial value `zero` through all elements of the collection.
* Traversal order is left-to-right.
* This is a terminal operation.
*/
def fold[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B) = { var b = zero; while (hasStep) { b = op(b, nextStep) }; b }
/** Repeatedly applies `op` to propagate an initial value `zero` through the collection until a condition `p` is met.
* If `p` is never met, the result of the last operation is returned.
* This is a terminal operation.
*/
def foldTo[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (!p(b) && hasStep) { b = op(b, nextStep) }; b }
/** Applies `f` to every remaining element in the collection.
* This is a terminal operation.
*/
def foreach(f: A => Unit) { while (hasStep) f(nextStep) }
/** Repeatedly merges elements with `op` until only a single element remains.
* Throws an exception if the `Stepper` is empty.
* Merging occurs from left to right.
* This is a terminal operation.
*/
def reduce(op: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = op(a, nextStep) }; a }
////
// Operations that convert to another related type
////
/** Returns this `Stepper` as a `java.util.Spliterator`.
* This is a terminal operation.
*/
def spliterator: Spliterator[A]
/** Returns this `Stepper` as a Scala `Iterator`.
* This is a terminal operation.
*/
def iterator: Iterator[A] = new scala.collection.AbstractIterator[A] {
def hasNext = self.hasStep
def next = self.nextStep
}
/** Returns a Scala collection of the type requested. */
def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, A, Coll[A]]): Coll[A] = {
val b = cbf()
while (hasStep) b += nextStep
b.result()
}
}
/** This trait indicates that a `Stepper` will implement `tryStep` in terms of `hasNext` and `nextStep`. */
trait NextStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, NextStepper[A]] {
def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false
def spliterator: Spliterator[A] = new ProxySpliteratorViaNext[A](this)
}
private[collectionImpl] class ProxySpliteratorViaNext[A](underlying: NextStepper[A]) extends Spliterator[A] {
def characteristics() = underlying.characteristics
def estimateSize() = underlying.knownSize
def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = if (underlying.hasStep) { f.accept(underlying.nextStep()); true } else false
def trySplit() = underlying.substep() match { case null => null; case x => new ProxySpliteratorViaNext[A](x) }
}
/** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`.
* Subclasses must implement `tryUncached` instead of `tryStep`, and should leave it protected, and must implement
* `knownUncachedSize` instead of `knownSize`. For speed, `foreachUncached` may also be overridden. It is recommended
* that all of the `Uncached` methods be left protected.
*/
trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] {
protected def myCache: A
protected def myCache_=(a: A): Unit
protected final var myCacheIsFull = false
private def load(): Boolean = {
myCacheIsFull = tryStep(myCache = _)
myCacheIsFull
}
final def hasStep = myCacheIsFull || load()
final def nextStep = {
if (!myCacheIsFull) {
load()
if (!myCacheIsFull) Stepper.throwNSEE
}
val ans = myCache
myCacheIsFull = false
myCache = null.asInstanceOf[A]
ans
}
final def knownSize = knownUncachedSize + (if (myCacheIsFull) 1 else 0)
protected def knownUncachedSize: Long
final def tryStep(f: A => Unit): Boolean = if (myCacheIsFull) { f(myCache); myCacheIsFull = false; true } else tryUncached(f)
protected def tryUncached(f: A => Unit): Boolean
final override def foreach(f: A => Unit) { if (myCacheIsFull) { f(myCache); myCacheIsFull = false }; foreachUncached(f) }
protected def foreachUncached(f: A => Unit) { while (tryUncached(f)) {} }
def spliterator: Spliterator[A] = new ProxySpliteratorViaTry[A](this)
}
private[collectionImpl] class ProxySpliteratorViaTry[A](underlying: TryStepper[A]) extends Spliterator[A] {
def characteristics() = underlying.characteristics
def estimateSize() = underlying.knownSize
def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = underlying.tryStep(a => f.accept(a))
override def forEachRemaining(f: java.util.function.Consumer[_ >: A]) { underlying.foreach(a => f.accept(a)) }
def trySplit() = underlying.substep() match { case null => null; case x => new ProxySpliteratorViaTry[A](x) }
}
/** Any `AnyStepper` combines the functionality of a Java `Iterator`, a Java `Spliterator`, and a `Stepper`. */
trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterator[A] with StepperLike[A, AnyStepper[A]] {
def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } }
def hasStep = hasNext()
def knownSize = getExactSizeIfKnown
def nextStep = next
def tryAdvance(c: java.util.function.Consumer[_ >: A]): Boolean = if (hasNext) { c.accept(next); true } else false
def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false
def trySplit() = substep
override def spliterator: Spliterator[A] = this
def seqStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, false)
def parStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, true)
}
private[collectionImpl] object AnyStepper {
final class BoxedDoubleStepper(st: DoubleStepper) extends AnyStepper[Double] {
def hasNext(): Boolean = st.hasNext()
def next(): Double = st.next()
def characteristics(): Int = st.characteristics()
def estimateSize(): Long = st.estimateSize()
def substep(): AnyStepper[Double] = new BoxedDoubleStepper(st.substep())
}
final class BoxedIntStepper(st: IntStepper) extends AnyStepper[Int] {
def hasNext(): Boolean = st.hasNext()
def next(): Int = st.next()
def characteristics(): Int = st.characteristics()
def estimateSize(): Long = st.estimateSize()
def substep(): AnyStepper[Int] = new BoxedIntStepper(st.substep())
}
final class BoxedLongStepper(st: LongStepper) extends AnyStepper[Long] {
def hasNext(): Boolean = st.hasNext()
def next(): Long = st.next()
def characteristics(): Int = st.characteristics()
def estimateSize(): Long = st.estimateSize()
def substep(): AnyStepper[Long] = new BoxedLongStepper(st.substep())
}
}
/** A `DoubleStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Double` values. */
trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble with StepperLike[Double, DoubleStepper] {
def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } }
def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } }
def hasStep = hasNext()
def knownSize = getExactSizeIfKnown
def nextStep = nextDouble
def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false
def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false
def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false
def trySplit() = substep
override def spliterator: Spliterator[Double] = this.asInstanceOf[Spliterator[Double]] // Scala and Java disagree about whether it's java.lang.Double or double
def seqStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, false)
def parStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, true)
}
/** An `IntStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Int` values. */
trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt with Spliterator.OfInt with StepperLike[Int, IntStepper] {
def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } }
def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } }
def hasStep = hasNext()
def knownSize = getExactSizeIfKnown
def nextStep = nextInt
def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false
def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false
def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false
def trySplit() = substep
override def spliterator: Spliterator[Int] = this.asInstanceOf[Spliterator[Int]] // Scala and Java disagree about whether it's java.lang.Integer or int
def seqStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, false)
def parStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, true)
}
/** A `LongStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Long` values. */
trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong with Spliterator.OfLong with StepperLike[Long, LongStepper] {
def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } }
def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } }
def hasStep = hasNext()
def knownSize = getExactSizeIfKnown
def nextStep = nextLong
def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false
def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false
def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false
def trySplit() = substep
override def spliterator: Spliterator[Long] = this.asInstanceOf[Spliterator[Long]] // Scala and Java disagree about whether it's java.lang.Long or long
def seqStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, false)
def parStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, true)
}
object Stepper {
/** Indicates that a Stepper delivers distinct values (e.g. is backed by a `Set`) */
val Distinct = Spliterator.DISTINCT
/** Indicates that a Stepper runs over an immutable collection */
val Immutable = Spliterator.IMMUTABLE
/** Indicates that a Stepper will not return any `null` values */
val NonNull = Spliterator.NONNULL
/** Indicates that a Stepper delivers elements in a particular order that should be maintained */
val Ordered = Spliterator.ORDERED
/** Indicates that a Stepper knows exactly how many elements it contains */
val Sized = Spliterator.SIZED
/** Indicates that a Stepper's children (created with substep()) will all know their size. Steppers that are SubSized must also be Sized. */
val SubSized = Spliterator.SUBSIZED
private[java8] final def throwNSEE: Nothing = throw new NoSuchElementException("Empty Stepper")
private class OfSpliterator[A](sp: Spliterator[A])
extends AnyStepper[A] with java.util.function.Consumer[A] {
private var cache: A = null.asInstanceOf[A]
private var cached: Boolean = false
def accept(a: A) { cache = a; cached = true }
private def loadCache: Boolean = sp.tryAdvance(this)
private def useCache(c: java.util.function.Consumer[_ >: A]): Boolean = {
if (cached) {
c.accept(cache)
cache = null.asInstanceOf[A]
cached = false
true
}
else false
}
def characteristics = sp.characteristics
def estimateSize = {
val sz = sp.estimateSize
if (cached && sz < Long.MaxValue && sz >= 0) sz + 1
else sz
}
override def forEachRemaining(c: java.util.function.Consumer[_ >: A]) {
useCache(c)
sp.forEachRemaining(c)
}
def hasNext = cached || loadCache
def next = {
if (!hasNext) throwNSEE
val ans = cache
cache = null.asInstanceOf[A]
cached = false
ans
}
def substep(): AnyStepper[A] = {
val subSp = sp.trySplit()
if (subSp eq null) null
else {
val sub = new OfSpliterator(subSp)
if (cached) {
sub.cache = cache
sub.cached = true
cache = null.asInstanceOf[A]
cached = false
}
sub
}
}
override def tryAdvance(c: java.util.function.Consumer[_ >: A]) = useCache(c) || sp.tryAdvance(c)
}
private class OfDoubleSpliterator(sp: Spliterator.OfDouble)
extends DoubleStepper with java.util.function.DoubleConsumer {
private var cache: Double = Double.NaN
private var cached: Boolean = false
def accept(d: Double) { cache = d; cached = true }
private def loadCache: Boolean = sp.tryAdvance(this)
private def useCache(c: java.util.function.DoubleConsumer): Boolean = {
if (cached) {
c.accept(cache)
cached = false
true
}
else false
}
def characteristics = sp.characteristics
def estimateSize = {
val sz = sp.estimateSize
if (cached && sz < Long.MaxValue && sz >= 0) sz + 1
else sz
}
override def forEachRemaining(c: java.util.function.DoubleConsumer) {
useCache(c)
sp.forEachRemaining(c)
}
def hasNext = cached || loadCache
def nextDouble = {
if (!hasNext) throwNSEE
val ans = cache
cached = false
ans
}
def substep(): DoubleStepper = {
val subSp = sp.trySplit()
if (subSp eq null) null
else {
val sub = new OfDoubleSpliterator(subSp)
if (cached) {
sub.cache = cache
sub.cached = true
cached = false
}
sub
}
}
override def tryAdvance(c: java.util.function.DoubleConsumer) = useCache(c) || sp.tryAdvance(c)
}
private class OfIntSpliterator(sp: Spliterator.OfInt)
extends IntStepper with java.util.function.IntConsumer {
private var cache: Int = 0
private var cached: Boolean = false
def accept(i: Int) { cache = i; cached = true }
private def loadCache: Boolean = sp.tryAdvance(this)
private def useCache(c: java.util.function.IntConsumer): Boolean = {
if (cached) {
c.accept(cache)
cached = false
true
}
else false
}
def characteristics = sp.characteristics
def estimateSize = {
val sz = sp.estimateSize
if (cached && sz < Long.MaxValue && sz >= 0) sz + 1
else sz
}
override def forEachRemaining(c: java.util.function.IntConsumer) {
useCache(c)
sp.forEachRemaining(c)
}
def hasNext = cached || loadCache
def nextInt = {
if (!hasNext) throwNSEE
val ans = cache
cached = false
ans
}
def substep(): IntStepper = {
val subSp = sp.trySplit()
if (subSp eq null) null
else {
val sub = new OfIntSpliterator(subSp)
if (cached) {
sub.cache = cache
sub.cached = true
cached = false
}
sub
}
}
override def tryAdvance(c: java.util.function.IntConsumer) = useCache(c) || sp.tryAdvance(c)
}
private class OfLongSpliterator(sp: Spliterator.OfLong)
extends LongStepper with java.util.function.LongConsumer {
private var cache: Long = 0L
private var cached: Boolean = false
def accept(l: Long) { cache = l; cached = true }
private def loadCache: Boolean = sp.tryAdvance(this)
private def useCache(c: java.util.function.LongConsumer): Boolean = {
if (cached) {
c.accept(cache)
cached = false
true
}
else false
}
def characteristics = sp.characteristics
def estimateSize = {
val sz = sp.estimateSize
if (cached && sz < Long.MaxValue && sz >= 0) sz + 1
else sz
}
override def forEachRemaining(c: java.util.function.LongConsumer) {
useCache(c)
sp.forEachRemaining(c)
}
def hasNext = cached || loadCache
def nextLong = {
if (!hasNext) throwNSEE
val ans = cache
cached = false
ans
}
def substep(): LongStepper = {
val subSp = sp.trySplit()
if (subSp eq null) null
else {
val sub = new OfLongSpliterator(subSp)
if (cached) {
sub.cache = cache
sub.cached = true
cached = false
}
sub
}
}
override def tryAdvance(c: java.util.function.LongConsumer) = useCache(c) || sp.tryAdvance(c)
}
/** Creates a `Stepper` over a generic `Spliterator`. */
def ofSpliterator[A](sp: Spliterator[A]): AnyStepper[A] = sp match {
case as: AnyStepper[A] => as
case s: DoubleStepper => new AnyStepper.BoxedDoubleStepper(s).asInstanceOf[AnyStepper[A]]
case s: IntStepper => new AnyStepper.BoxedIntStepper(s).asInstanceOf[AnyStepper[A]]
case s: LongStepper => new AnyStepper.BoxedLongStepper(s).asInstanceOf[AnyStepper[A]]
case _ => new OfSpliterator[A](sp)
}
/** Creates a `Stepper` over a `DoubleSpliterator`. */
def ofSpliterator(sp: Spliterator.OfDouble): DoubleStepper = sp match {
case ds: DoubleStepper => ds
case _ => new OfDoubleSpliterator(sp)
}
/** Creates a `Stepper` over an `IntSpliterator`. */
def ofSpliterator(sp: Spliterator.OfInt): IntStepper = sp match {
case is: IntStepper => is
case _ => new OfIntSpliterator(sp)
}
/** Creates a `Stepper` over a `LongSpliterator`. */
def ofSpliterator(sp: Spliterator.OfLong): LongStepper = sp match {
case ls: LongStepper => ls
case _ => new OfLongSpliterator(sp)
}
/* These adapter classes can wrap an AnyStepper of a small numeric type into the appropriately widened
* primitive Stepper type. This provides a basis for more efficient stream processing on unboxed values
* provided that the original source of the data is already boxed. In other cases the widening conversion
* should always be performed directly on the original unboxed values in a custom Stepper implementation
* (see for example StepsWidenedByteArray). */
private[java8] class WideningByteStepper(st: AnyStepper[Byte]) extends IntStepper {
def hasNext(): Boolean = st.hasNext()
def nextInt(): Int = st.next()
def characteristics(): Int = st.characteristics() | NonNull
def estimateSize(): Long = st.estimateSize()
def substep(): IntStepper = new WideningByteStepper(st.substep())
}
private[java8] class WideningCharStepper(st: AnyStepper[Char]) extends IntStepper {
def hasNext(): Boolean = st.hasNext()
def nextInt(): Int = st.next()
def characteristics(): Int = st.characteristics() | NonNull
def estimateSize(): Long = st.estimateSize()
def substep(): IntStepper = new WideningCharStepper(st.substep())
}
private[java8] class WideningShortStepper(st: AnyStepper[Short]) extends IntStepper {
def hasNext(): Boolean = st.hasNext()
def nextInt(): Int = st.next()
def characteristics(): Int = st.characteristics() | NonNull
def estimateSize(): Long = st.estimateSize()
def substep(): IntStepper = new WideningShortStepper(st.substep())
}
private[java8] class WideningFloatStepper(st: AnyStepper[Float]) extends DoubleStepper {
def hasNext(): Boolean = st.hasNext()
def nextDouble(): Double = st.next()
def characteristics(): Int = st.characteristics() | NonNull
def estimateSize(): Long = st.estimateSize()
def substep(): DoubleStepper = new WideningFloatStepper(st.substep())
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy