Skip to content

Commit b175a03

Browse files
committed
Merge pull request #65 from szeiger/wip/stream-improvements
Improvements to Java 8 Stream support
2 parents 6caeefa + cfee33d commit b175a03

29 files changed

+305
-427
lines changed

src/main/java/scala/compat/java8/ScalaStreaming.java renamed to src/main/java/scala/compat/java8/ScalaStreamSupport.java

Lines changed: 93 additions & 83 deletions
Large diffs are not rendered by default.

src/main/java/scala/compat/java8/runtime/CollectionInternals.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package scala.compat.java8.runtime;
22

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

55
public class CollectionInternals {
66
public static <A> Object[] getTable(scala.collection.mutable.FlatHashTable<A> fht) { return fht.hashTableContents().table(); }

src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,13 @@ object PrimitiveIteratorConverters {
9696
}
9797

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

104104
/** Provides conversions from Scala `Iterator` to manually specialized `PrimitiveIterator` variants, when available */
105-
implicit class RichIteratorToPrimitives[A](val underlying: Iterator[A]) extends AnyVal {
105+
implicit final class RichIteratorToPrimitives[A](private val underlying: Iterator[A]) extends AnyVal {
106106
/** Wraps this `scala.collection.Iterator` as a manually specialized `java.util.PrimitiveIterator` variant, if possible */
107107
def asPrimitive[That](implicit specOp: SpecializerOfIterators[A, That]): That = specOp.fromScala(underlying)
108108
}

src/main/scala/scala/compat/java8/SpliteratorConverters.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ package SpliteratorConverters {
1717

1818

1919
package object SpliteratorConverters extends SpliteratorConverters.Priority2SpliteratorConverters {
20-
implicit class SpliteratorOfDoubleToStepper(private val underlying: Spliterator.OfDouble) extends AnyVal {
20+
implicit final class SpliteratorOfDoubleToStepper(private val underlying: Spliterator.OfDouble) extends AnyVal {
2121
def stepper: DoubleStepper = Stepper.ofSpliterator(underlying)
2222
}
23-
implicit class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal {
23+
implicit final class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal {
2424
def stepper: IntStepper = Stepper.ofSpliterator(underlying)
2525
}
26-
implicit class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal {
26+
implicit final class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal {
2727
def stepper: LongStepper = Stepper.ofSpliterator(underlying)
2828
}
2929
}

src/main/scala/scala/compat/java8/StreamConverters.scala

Lines changed: 65 additions & 83 deletions
Large diffs are not rendered by default.

src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator
246246
i = 0
247247
}
248248

249-
def characteristics = ORDERED | SIZED | SUBSIZED
249+
def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL
250250

251251
def estimateSize = N
252252

src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) exte
253253
i = 0
254254
}
255255

256-
def characteristics = ORDERED | SIZED | SUBSIZED
256+
def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL
257257

258258
def estimateSize = N
259259

src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) ex
247247
i = 0
248248
}
249249

250-
def characteristics = ORDERED | SIZED | SUBSIZED
250+
def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL
251251

252252
def estimateSize = N
253253

src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ trait EfficientSubstep {}
5353

5454
/** Provides functionality for Stepper while keeping track of a more precise type of the collection.
5555
*/
56-
trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self =>
56+
trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self: CC =>
5757
/** Characteristics are bit flags that indicate runtime characteristics of this Stepper.
5858
*
5959
* - `Distinct` means that no duplicates exist
@@ -90,9 +90,6 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self =>
9090
*/
9191
def substep(): CC
9292

93-
/** Returns the precise underlying type of this `Stepper`. */
94-
def typedPrecisely: CC
95-
9693
/** Warns this `Stepper` that it is likely to be used in a parallel context (used for efficiency only) */
9794
def anticipateParallelism: this.type = this
9895

@@ -236,13 +233,38 @@ trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterat
236233
def nextStep = next
237234
def tryAdvance(c: java.util.function.Consumer[_ >: A]): Boolean = if (hasNext) { c.accept(next); true } else false
238235
def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false
239-
def trySplit() = substep match { case null => null; case x => x.typedPrecisely }
240-
final def typedPrecisely: AnyStepper[A] = this
236+
def trySplit() = substep
241237
override def spliterator: Spliterator[A] = this
242238
def seqStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, false)
243239
def parStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, true)
244240
}
245241

242+
object AnyStepper {
243+
private[collectionImpl] class BoxedDoubleStepper(st: DoubleStepper) extends AnyStepper[Double] {
244+
def hasNext(): Boolean = st.hasNext()
245+
def next(): Double = st.next()
246+
def characteristics(): Int = st.characteristics()
247+
def estimateSize(): Long = st.estimateSize()
248+
def substep(): AnyStepper[Double] = new BoxedDoubleStepper(st.substep())
249+
}
250+
251+
private[collectionImpl] class BoxedIntStepper(st: IntStepper) extends AnyStepper[Int] {
252+
def hasNext(): Boolean = st.hasNext()
253+
def next(): Int = st.next()
254+
def characteristics(): Int = st.characteristics()
255+
def estimateSize(): Long = st.estimateSize()
256+
def substep(): AnyStepper[Int] = new BoxedIntStepper(st.substep())
257+
}
258+
259+
private[collectionImpl] class BoxedLongStepper(st: LongStepper) extends AnyStepper[Long] {
260+
def hasNext(): Boolean = st.hasNext()
261+
def next(): Long = st.next()
262+
def characteristics(): Int = st.characteristics()
263+
def estimateSize(): Long = st.estimateSize()
264+
def substep(): AnyStepper[Long] = new BoxedLongStepper(st.substep())
265+
}
266+
}
267+
246268
/** A `DoubleStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Double` values. */
247269
trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble with StepperLike[Double, DoubleStepper] {
248270
def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } }
@@ -253,8 +275,7 @@ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfD
253275
def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false
254276
def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false
255277
def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false
256-
def trySplit() = substep match { case null => null; case x => x.typedPrecisely }
257-
final def typedPrecisely: DoubleStepper = this
278+
def trySplit() = substep
258279
override def spliterator: Spliterator[Double] = this.asInstanceOf[Spliterator[Double]] // Scala and Java disagree about whether it's java.lang.Double or double
259280
def seqStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, false)
260281
def parStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, true)
@@ -270,8 +291,7 @@ trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt wit
270291
def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false
271292
def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false
272293
def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false
273-
def trySplit() = substep match { case null => null; case x => x.typedPrecisely }
274-
final def typedPrecisely = this
294+
def trySplit() = substep
275295
override def spliterator: Spliterator[Int] = this.asInstanceOf[Spliterator[Int]] // Scala and Java disagree about whether it's java.lang.Integer or int
276296
def seqStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, false)
277297
def parStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, true)
@@ -287,8 +307,7 @@ trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong
287307
def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false
288308
def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false
289309
def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false
290-
def trySplit() = substep match { case null => null; case x => x.typedPrecisely }
291-
final def typedPrecisely = this
310+
def trySplit() = substep
292311
override def spliterator: Spliterator[Long] = this.asInstanceOf[Spliterator[Long]] // Scala and Java disagree about whether it's java.lang.Long or long
293312
def seqStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, false)
294313
def parStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, true)
@@ -519,6 +538,9 @@ object Stepper {
519538
/** Creates a `Stepper` over a generic `Spliterator`. */
520539
def ofSpliterator[A](sp: Spliterator[A]): AnyStepper[A] = sp match {
521540
case as: AnyStepper[A] => as
541+
case s: DoubleStepper => new AnyStepper.BoxedDoubleStepper(s).asInstanceOf[AnyStepper[A]]
542+
case s: IntStepper => new AnyStepper.BoxedIntStepper(s).asInstanceOf[AnyStepper[A]]
543+
case s: LongStepper => new AnyStepper.BoxedLongStepper(s).asInstanceOf[AnyStepper[A]]
522544
case _ => new OfSpliterator[A](sp)
523545
}
524546

src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala

Lines changed: 10 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -11,150 +11,21 @@ trait MakesSequentialStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends
1111
}
1212

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

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

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

30-
/** Classes or objects implementing this trait create generic steppers for map values suitable for sequential use. */
31-
trait MakesAnyValueSeqStepper[A] extends Any {
32-
/** Generates a fresh stepper over map values of type `A` suitable for sequential use */
33-
def valueStepper: AnyStepper[A]
34-
}
35-
36-
/** Classes or objects implementing this trait create `Double` steppers suitable for sequential use. */
37-
trait MakesDoubleSeqStepper extends Any {
38-
/** Generates a fresh stepper over `Double`s suitable for sequential use */
39-
def stepper: DoubleStepper
40-
}
41-
42-
/** Classes or objects implementing this trait create `Double` steppers for map keys suitable for sequential use. */
43-
trait MakesDoubleKeySeqStepper extends Any {
44-
/** Generates a fresh stepper over map keys of type `Double` suitable for sequential use */
45-
def keyStepper: DoubleStepper
46-
}
47-
48-
/** Classes or objects implementing this trait create `Double` steppers for map values suitable for sequential use. */
49-
trait MakesDoubleValueSeqStepper extends Any {
50-
/** Generates a fresh stepper over map values of type `Double` suitable for sequential use */
51-
def valueStepper: DoubleStepper
52-
}
53-
54-
/** Classes or objects implementing this trait create `Int` steppers suitable for sequential use. */
55-
trait MakesIntSeqStepper extends Any {
56-
/** Generates a fresh stepper over `Int`s suitable for sequential use */
57-
def stepper: IntStepper
58-
}
59-
60-
/** Classes or objects implementing this trait create `Int` steppers for map keys suitable for sequential use. */
61-
trait MakesIntKeySeqStepper extends Any {
62-
/** Generates a fresh stepper over map keys of type `Int` suitable for sequential use */
63-
def keyStepper: IntStepper
64-
}
65-
66-
/** Classes or objects implementing this trait create `Int` steppers for map values suitable for sequential use. */
67-
trait MakesIntValueSeqStepper extends Any {
68-
/** Generates a fresh stepper over map values of type `Int` suitable for sequential use */
69-
def valueStepper: IntStepper
70-
}
71-
72-
/** Classes or objects implementing this trait create `Long` steppers suitable for sequential use. */
73-
trait MakesLongSeqStepper extends Any {
74-
/** Generates a fresh stepper over `Long`s suitable for sequential use */
75-
def stepper: LongStepper
76-
}
77-
78-
/** Classes or objects implementing this trait create `Long` steppers for map keys suitable for sequential use. */
79-
trait MakesLongKeySeqStepper extends Any {
80-
/** Generates a fresh stepper over map keys of type `Long` suitable for sequential use */
81-
def keyStepper: LongStepper
82-
}
83-
84-
/** Classes or objects implementing this trait create `Long` steppers for map values suitable for sequential use. */
85-
trait MakesLongValueSeqStepper extends Any {
86-
/** Generates a fresh stepper over map values of type `Long` suitable for sequential use */
87-
def valueStepper: LongStepper
88-
}
89-
90-
/** Classes or objects implementing this trait create generic steppers suitable for sequential or parallel use. */
91-
trait MakesAnyStepper[A] extends Any {
92-
/** Generates a fresh stepper over `A`s that can be efficiently subdivided */
93-
def stepper: AnyStepper[A] with EfficientSubstep
94-
}
95-
96-
/** Classes or objects implementing this trait create generic steppers for map keys suitable for sequential or parallel use. */
97-
trait MakesAnyKeyStepper[A] extends Any {
98-
/** Generates a fresh stepper over map keys of type `A` that can be efficiently subdivided */
99-
def keyStepper: AnyStepper[A] with EfficientSubstep
100-
}
101-
102-
/** Classes or objects implementing this trait create generic steppers for map values suitable for sequential or parallel use. */
103-
trait MakesAnyValueStepper[A] extends Any {
104-
/** Generates a fresh stepper over map values of type `A` that can be efficiently subdivided */
105-
def valueStepper: AnyStepper[A] with EfficientSubstep
106-
}
107-
108-
/** Classes or objects implementing this trait create `Double` steppers suitable for sequential or parallel use. */
109-
trait MakesDoubleStepper extends Any {
110-
/** Generates a fresh stepper over `Double`s that can be efficiently subdivided */
111-
def stepper: DoubleStepper with EfficientSubstep
112-
}
113-
114-
/** Classes or objects implementing this trait create `Double` steppers for map keys suitable for sequential or parallel use. */
115-
trait MakesDoubleKeyStepper extends Any {
116-
/** Generates a fresh stepper over map keys of type `Double` that can be efficiently subdivided */
117-
def keyStepper: DoubleStepper with EfficientSubstep
118-
}
119-
120-
/** Classes or objects implementing this trait create `Double` steppers for map values suitable for sequential or parallel use. */
121-
trait MakesDoubleValueStepper extends Any {
122-
/** Generates a fresh stepper over map values of type `Double` that can be efficiently subdivided */
123-
def valueStepper: DoubleStepper with EfficientSubstep
124-
}
125-
126-
/** Classes or objects implementing this trait create `Int` steppers suitable for sequential or parallel use. */
127-
trait MakesIntStepper extends Any {
128-
/** Generates a fresh stepper over `Int`s that can be efficiently subdivided */
129-
def stepper: IntStepper with EfficientSubstep
130-
}
131-
132-
/** Classes or objects implementing this trait create `Int` steppers for map keys suitable for sequential or parallel use. */
133-
trait MakesIntKeyStepper extends Any {
134-
/** Generates a fresh stepper over map keys of type `Int` that can be efficiently subdivided */
135-
def keyStepper: IntStepper with EfficientSubstep
136-
}
137-
138-
/** Classes or objects implementing this trait create `Int` steppers for map values suitable for sequential or parallel use. */
139-
trait MakesIntValueStepper extends Any {
140-
/** Generates a fresh stepper over map values of type `Int` that can be efficiently subdivided */
141-
def valueStepper: IntStepper with EfficientSubstep
142-
}
143-
144-
/** Classes or objects implementing this trait create `Long` steppers suitable for sequential or parallel use. */
145-
trait MakesLongStepper extends Any {
146-
/** Generates a fresh stepper over `Long`s that can be efficiently subdivided */
147-
def stepper: LongStepper with EfficientSubstep
148-
}
149-
150-
/** Classes or objects implementing this trait create `Long` steppers for map keys suitable for sequential or parallel use. */
151-
trait MakesLongKeyStepper extends Any {
152-
/** Generates a fresh stepper over map keys of type `Long` that can be efficiently subdivided */
153-
def keyStepper: LongStepper with EfficientSubstep
154-
}
155-
156-
/** Classes or objects implementing this trait create `Long` steppers for map values suitable for sequential or parallel use. */
157-
trait MakesLongValueStepper extends Any {
158-
/** Generates a fresh stepper over map values of type `Long` that can be efficiently subdivided */
159-
def valueStepper: LongStepper with EfficientSubstep
28+
trait MakesValueStepper[+T <: Stepper[_]] extends Any {
29+
/** Generates a fresh stepper of type `T` over map values */
30+
def valueStepper: T
16031
}

0 commit comments

Comments
 (0)