Skip to content

Improvements to Java 8 Stream support #65

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 1, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package scala.compat.java8.runtime;

import scala.collection.immutable.*; // Don't rely on this! Refer to everything explicitly!
// No imports! All type names are fully qualified to avoid confusion!

public class CollectionInternals {
public static <A> Object[] getTable(scala.collection.mutable.FlatHashTable<A> fht) { return fht.hashTableContents().table(); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,13 @@ object PrimitiveIteratorConverters {
}

/** Provides conversions from Java `Iterator` to manually specialized `PrimitiveIterator` variants, when available */
implicit class RichJavaIteratorToPrimitives[A](val underlying: JIterator[A]) extends AnyVal {
implicit final class RichJavaIteratorToPrimitives[A](private val underlying: JIterator[A]) extends AnyVal {
/** Wraps this `java.util.Iterator` as a manually specialized variant, if possible */
def asPrimitive[That](implicit specOp: SpecializerOfIterators[A, That]): That = specOp.fromJava(underlying)
}

/** Provides conversions from Scala `Iterator` to manually specialized `PrimitiveIterator` variants, when available */
implicit class RichIteratorToPrimitives[A](val underlying: Iterator[A]) extends AnyVal {
implicit final class RichIteratorToPrimitives[A](private val underlying: Iterator[A]) extends AnyVal {
/** Wraps this `scala.collection.Iterator` as a manually specialized `java.util.PrimitiveIterator` variant, if possible */
def asPrimitive[That](implicit specOp: SpecializerOfIterators[A, That]): That = specOp.fromScala(underlying)
}
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/scala/compat/java8/SpliteratorConverters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ package SpliteratorConverters {


package object SpliteratorConverters extends SpliteratorConverters.Priority2SpliteratorConverters {
implicit class SpliteratorOfDoubleToStepper(private val underlying: Spliterator.OfDouble) extends AnyVal {
implicit final class SpliteratorOfDoubleToStepper(private val underlying: Spliterator.OfDouble) extends AnyVal {
def stepper: DoubleStepper = Stepper.ofSpliterator(underlying)
}
implicit class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal {
implicit final class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal {
def stepper: IntStepper = Stepper.ofSpliterator(underlying)
}
implicit class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal {
implicit final class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal {
def stepper: LongStepper = Stepper.ofSpliterator(underlying)
}
}
148 changes: 65 additions & 83 deletions src/main/scala/scala/compat/java8/StreamConverters.scala

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator
i = 0
}

def characteristics = ORDERED | SIZED | SUBSIZED
def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL

def estimateSize = N

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) exte
i = 0
}

def characteristics = ORDERED | SIZED | SUBSIZED
def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL

def estimateSize = N

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) ex
i = 0
}

def characteristics = ORDERED | SIZED | SUBSIZED
def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL

def estimateSize = N

Expand Down
46 changes: 34 additions & 12 deletions src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ 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 =>
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
Expand Down Expand Up @@ -90,9 +90,6 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self =>
*/
def substep(): CC

/** Returns the precise underlying type of this `Stepper`. */
def typedPrecisely: CC

/** Warns this `Stepper` that it is likely to be used in a parallel context (used for efficiency only) */
def anticipateParallelism: this.type = this

Expand Down Expand Up @@ -236,13 +233,38 @@ trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterat
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 match { case null => null; case x => x.typedPrecisely }
final def typedPrecisely: AnyStepper[A] = this
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)
}

object AnyStepper {
private[collectionImpl] 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())
}

private[collectionImpl] 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())
}

private[collectionImpl] 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)) } }
Expand All @@ -253,8 +275,7 @@ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfD
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 match { case null => null; case x => x.typedPrecisely }
final def typedPrecisely: DoubleStepper = this
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)
Expand All @@ -270,8 +291,7 @@ trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt wit
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 match { case null => null; case x => x.typedPrecisely }
final def typedPrecisely = this
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)
Expand All @@ -287,8 +307,7 @@ trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong
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 match { case null => null; case x => x.typedPrecisely }
final def typedPrecisely = this
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)
Expand Down Expand Up @@ -519,6 +538,9 @@ object Stepper {
/** 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)
}

Expand Down
149 changes: 10 additions & 139 deletions src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,150 +11,21 @@ trait MakesSequentialStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends
}

/** Classes or objects implementing this trait create streams suitable for parallel use */
trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any with MakesSequentialStream[A, SS] {
trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any {
def parStream: SS
}

/** Classes or objects implementing this trait create generic steppers suitable for sequential use. */
trait MakesAnySeqStepper[A] extends Any {
/** Generates a fresh stepper over `A`s suitable for sequential use */
def stepper: AnyStepper[A]
trait MakesStepper[+T <: Stepper[_]] extends Any {
/** Generates a fresh stepper of type `T` */
def stepper: T
}

/** Classes or objects implementing this trait create generic steppers for map keys suitable for sequential use. */
trait MakesAnyKeySeqStepper[A] extends Any {
/** Generates a fresh stepper over map keys of type `A` suitable for sequential use */
def keyStepper: AnyStepper[A]
trait MakesKeyStepper[+T <: Stepper[_]] extends Any {
/** Generates a fresh stepper of type `T` over map keys */
def keyStepper: T
}

/** Classes or objects implementing this trait create generic steppers for map values suitable for sequential use. */
trait MakesAnyValueSeqStepper[A] extends Any {
/** Generates a fresh stepper over map values of type `A` suitable for sequential use */
def valueStepper: AnyStepper[A]
}

/** Classes or objects implementing this trait create `Double` steppers suitable for sequential use. */
trait MakesDoubleSeqStepper extends Any {
/** Generates a fresh stepper over `Double`s suitable for sequential use */
def stepper: DoubleStepper
}

/** Classes or objects implementing this trait create `Double` steppers for map keys suitable for sequential use. */
trait MakesDoubleKeySeqStepper extends Any {
/** Generates a fresh stepper over map keys of type `Double` suitable for sequential use */
def keyStepper: DoubleStepper
}

/** Classes or objects implementing this trait create `Double` steppers for map values suitable for sequential use. */
trait MakesDoubleValueSeqStepper extends Any {
/** Generates a fresh stepper over map values of type `Double` suitable for sequential use */
def valueStepper: DoubleStepper
}

/** Classes or objects implementing this trait create `Int` steppers suitable for sequential use. */
trait MakesIntSeqStepper extends Any {
/** Generates a fresh stepper over `Int`s suitable for sequential use */
def stepper: IntStepper
}

/** Classes or objects implementing this trait create `Int` steppers for map keys suitable for sequential use. */
trait MakesIntKeySeqStepper extends Any {
/** Generates a fresh stepper over map keys of type `Int` suitable for sequential use */
def keyStepper: IntStepper
}

/** Classes or objects implementing this trait create `Int` steppers for map values suitable for sequential use. */
trait MakesIntValueSeqStepper extends Any {
/** Generates a fresh stepper over map values of type `Int` suitable for sequential use */
def valueStepper: IntStepper
}

/** Classes or objects implementing this trait create `Long` steppers suitable for sequential use. */
trait MakesLongSeqStepper extends Any {
/** Generates a fresh stepper over `Long`s suitable for sequential use */
def stepper: LongStepper
}

/** Classes or objects implementing this trait create `Long` steppers for map keys suitable for sequential use. */
trait MakesLongKeySeqStepper extends Any {
/** Generates a fresh stepper over map keys of type `Long` suitable for sequential use */
def keyStepper: LongStepper
}

/** Classes or objects implementing this trait create `Long` steppers for map values suitable for sequential use. */
trait MakesLongValueSeqStepper extends Any {
/** Generates a fresh stepper over map values of type `Long` suitable for sequential use */
def valueStepper: LongStepper
}

/** Classes or objects implementing this trait create generic steppers suitable for sequential or parallel use. */
trait MakesAnyStepper[A] extends Any {
/** Generates a fresh stepper over `A`s that can be efficiently subdivided */
def stepper: AnyStepper[A] with EfficientSubstep
}

/** Classes or objects implementing this trait create generic steppers for map keys suitable for sequential or parallel use. */
trait MakesAnyKeyStepper[A] extends Any {
/** Generates a fresh stepper over map keys of type `A` that can be efficiently subdivided */
def keyStepper: AnyStepper[A] with EfficientSubstep
}

/** Classes or objects implementing this trait create generic steppers for map values suitable for sequential or parallel use. */
trait MakesAnyValueStepper[A] extends Any {
/** Generates a fresh stepper over map values of type `A` that can be efficiently subdivided */
def valueStepper: AnyStepper[A] with EfficientSubstep
}

/** Classes or objects implementing this trait create `Double` steppers suitable for sequential or parallel use. */
trait MakesDoubleStepper extends Any {
/** Generates a fresh stepper over `Double`s that can be efficiently subdivided */
def stepper: DoubleStepper with EfficientSubstep
}

/** Classes or objects implementing this trait create `Double` steppers for map keys suitable for sequential or parallel use. */
trait MakesDoubleKeyStepper extends Any {
/** Generates a fresh stepper over map keys of type `Double` that can be efficiently subdivided */
def keyStepper: DoubleStepper with EfficientSubstep
}

/** Classes or objects implementing this trait create `Double` steppers for map values suitable for sequential or parallel use. */
trait MakesDoubleValueStepper extends Any {
/** Generates a fresh stepper over map values of type `Double` that can be efficiently subdivided */
def valueStepper: DoubleStepper with EfficientSubstep
}

/** Classes or objects implementing this trait create `Int` steppers suitable for sequential or parallel use. */
trait MakesIntStepper extends Any {
/** Generates a fresh stepper over `Int`s that can be efficiently subdivided */
def stepper: IntStepper with EfficientSubstep
}

/** Classes or objects implementing this trait create `Int` steppers for map keys suitable for sequential or parallel use. */
trait MakesIntKeyStepper extends Any {
/** Generates a fresh stepper over map keys of type `Int` that can be efficiently subdivided */
def keyStepper: IntStepper with EfficientSubstep
}

/** Classes or objects implementing this trait create `Int` steppers for map values suitable for sequential or parallel use. */
trait MakesIntValueStepper extends Any {
/** Generates a fresh stepper over map values of type `Int` that can be efficiently subdivided */
def valueStepper: IntStepper with EfficientSubstep
}

/** Classes or objects implementing this trait create `Long` steppers suitable for sequential or parallel use. */
trait MakesLongStepper extends Any {
/** Generates a fresh stepper over `Long`s that can be efficiently subdivided */
def stepper: LongStepper with EfficientSubstep
}

/** Classes or objects implementing this trait create `Long` steppers for map keys suitable for sequential or parallel use. */
trait MakesLongKeyStepper extends Any {
/** Generates a fresh stepper over map keys of type `Long` that can be efficiently subdivided */
def keyStepper: LongStepper with EfficientSubstep
}

/** Classes or objects implementing this trait create `Long` steppers for map values suitable for sequential or parallel use. */
trait MakesLongValueStepper extends Any {
/** Generates a fresh stepper over map values of type `Long` that can be efficiently subdivided */
def valueStepper: LongStepper with EfficientSubstep
trait MakesValueStepper[+T <: Stepper[_]] extends Any {
/** Generates a fresh stepper of type `T` over map values */
def valueStepper: T
}
Loading