diff --git a/.travis.yml b/.travis.yml index c8f9482..24e00c5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,7 @@ jdk: - openjdk11 scala: - # no 2.13 for now in cross-build because of - # https://github.com/scala/scala-java8-compat/issues/97 - - 2.11.12 - - 2.12.8 + - 2.13.0-RC2 env: global: diff --git a/README.md b/README.md index 2c5539f..224222f 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ as the collection can (in some cases) be built in parallel. Because the wrappers are invoked based on the static type of the collection, there are also cases where parallelization is inefficient when interfacing with Java 8 Streams (e.g. when a collection is typed as `Seq[String]` so might have linear -access like `List`, but actually is a `WrappedArray[String]` that can be efficiently parallelized) but can be efficient +access like `List`, but actually is an `ArraySeq[String]` that can be efficiently parallelized) but can be efficient with Scala parallel collections. The `parStream` method is only available when the static type is known to be compatible with rapid parallel operation; `seqStream` can be parallelized by using `.parallel`, but may or may not be efficient. diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index 07d021d..5f0bb49 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -233,7 +233,7 @@ package object generate { implicit val arrayIntToIterator: (Array[Int] => Iterator[Int]) = (a: Array[Int]) => new Iterator[Int] { private[this] var i = 0 def hasNext = i < a.length - def next = if (hasNext) { var ans = a(i); i += 1; ans } else throw new NoSuchElementException(i.toString) + def next() = if (hasNext) { var ans = a(i); i += 1; ans } else throw new NoSuchElementException(i.toString) } implicit val arrayStringToIterator: (Array[String] => Iterator[String]) = _.iterator } @@ -268,7 +268,7 @@ package object generate { class MuqThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.Queue]("mutable.Queue") {} - class WraThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.WrappedArray]("mutable.WrappedArray") {} + class AsqThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.ArraySeq]("mutable.ArraySeq") {} class JixThings(val sizes: Array[Int]) extends AbstractThings[java.util.ArrayList]("java.util.ArrayList") {} @@ -291,7 +291,7 @@ package object generate { lazy val lhs = new LhsThings(sizes) lazy val prq = new PrqThings(sizes) lazy val muq = new MuqThings(sizes) - lazy val wra = new WraThings(sizes) + lazy val asq = new AsqThings(sizes) lazy val jix = new JixThings(sizes) lazy val jln = new JlnThings(sizes) } diff --git a/benchmark/src/main/scala/bench/ParseJmhLog.scala b/benchmark/src/main/scala/bench/ParseJmhLog.scala index 0263c45..5a4bdec 100644 --- a/benchmark/src/main/scala/bench/ParseJmhLog.scala +++ b/benchmark/src/main/scala/bench/ParseJmhLog.scala @@ -36,7 +36,7 @@ object ParseJmhLog { "stm" -> "collection.immutable.Stream", "trs" -> "collection.immutable.TreeSet", "vec" -> "collection.immutable.Vector", - "wra" -> "collection.mutable.WrappedArray", + "asq" -> "collection.mutable.ArraySeq", "jix" -> "java.util.ArrayList", "jln" -> "java.util.LinkedList" ) diff --git a/build.sbt b/build.sbt index f9493cc..0cf740d 100644 --- a/build.sbt +++ b/build.sbt @@ -1,8 +1,6 @@ import ScalaModulePlugin._ -// no 2.13 for now in cross-build because of -// https://github.com/scala/scala-java8-compat/issues/97 -crossScalaVersions in ThisBuild := List("2.12.8", "2.11.12") +crossScalaVersions in ThisBuild := List("2.13.0-RC2") val disableDocs = sys.props("nodocs") == "true" || diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala index 26acee7..7045f0b 100644 --- a/fnGen/WrapFnGen.scala +++ b/fnGen/WrapFnGen.scala @@ -66,12 +66,14 @@ object WrapFnGen { } implicit class SplitMyLinesAndStuff(s: String) { - def toVec = s.linesIterator.toVector + // work around scala/bug#11125 + def toVec = Predef.augmentString(s).lines.toVector def nonBlank = s.trim.length > 0 } implicit class TreeToText(t: Tree) { - def text = showCode(t).replace("$", "").linesIterator.toVector + // work around scala/bug#11125 + def text = Predef.augmentString(showCode(t).replace("$", "")).lines.toVector } case class Prioritized(lines: Vector[String], priority: Int) { @@ -245,7 +247,7 @@ object WrapFnGen { numberedA ++= scalaTargs.map(_.toString).collect{ case An(digits) if (digits.length < 10) => digits.toInt } val scalafnTnames = (jfn.pTypes :+ jfn.rType).zipWithIndex.map{ case (pt, i) if (i < jfn.pTypes.length && pt.isFinalType) || (!pt.isFinalType && jfn.pTypes.take(i).exists(_ == pt)) => - val j = Iterator.from(i).dropWhile(numberedA).next + val j = Iterator.from(i).dropWhile(numberedA).next() val genericName = TypeName(s"A$j") numberedA += j evidences += ((genericName, pt.typeSymbol.name.toTypeName)) @@ -296,7 +298,8 @@ object WrapFnGen { def sameText(f: java.io.File, text: String): Boolean = { val x = scala.io.Source.fromFile(f) val lines = try { x.getLines.toVector } finally { x.close } - lines.iterator.filter(_.nonBlank) == text.linesIterator.filter(_.nonBlank) + // work around scala/bug#11125 + lines.iterator.filter(_.nonBlank) == Predef.augmentString(text).lines.filter(_.nonBlank) } def write(f: java.io.File, text: String): Unit = { @@ -309,6 +312,6 @@ object WrapFnGen { def main(args: Array[String]): Unit = { val names = args.iterator.map(x => new java.io.File(x)) - write(names.next, converterContents) + write(names.next(), converterContents) } } diff --git a/project/CodeGen.scala b/project/CodeGen.scala index 4289973..b3f3f11 100644 --- a/project/CodeGen.scala +++ b/project/CodeGen.scala @@ -519,9 +519,9 @@ object CodeGen { val specialized = List("V", "V,IJFD", "V,IJD,IJD").flatMap(specialize).map { case (i, a, sp) => - s" public static scala.Function$i<$a> procSpecialized(JFunction$i$sp f) { return f; }" } ++ + s" public static scala.Function$i<$a> procSpecialized(JFunction$i$sp f) { return (scala.Function$i<$a>)(Object)f; }" } ++ List("BSIJCFDZ", "ZIFJD,IJFD", "ZIFJD,IJD,IJD").flatMap(specialize).map { case (i, a, sp) => - s" public static scala.Function$i<$a> funcSpecialized(JFunction$i$sp f) { return f; }" } + s" public static scala.Function$i<$a> funcSpecialized(JFunction$i$sp f) { return (scala.Function$i<$a>)(Object)f; }" } (blocks.map(_._1) ++ blocks.map(_._2)) :+ ( "JFunction", diff --git a/src/main/java/scala/compat/java8/ScalaStreamSupport.java b/src/main/java/scala/compat/java8/ScalaStreamSupport.java index bc21ca8..a992c72 100644 --- a/src/main/java/scala/compat/java8/ScalaStreamSupport.java +++ b/src/main/java/scala/compat/java8/ScalaStreamSupport.java @@ -12,10 +12,10 @@ package scala.compat.java8; -import scala.compat.java8.converterImpl.*; -import scala.compat.java8.collectionImpl.*; import java.util.stream.*; -import scala.compat.java8.runtime.CollectionInternals; + +import scala.collection.*; +import scala.jdk.javaapi.StreamConverters; /** * This class contains static utility methods for creating Java Streams from Scala Collections, similar @@ -33,203 +33,62 @@ public class ScalaStreamSupport { ///////////////////// /** - * Generates a Stream that traverses an IndexedSeq. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The IndexedSeq to traverse - * @return A Stream view of the collection which, by default, executes sequentially. - */ - public static Stream stream(scala.collection.IndexedSeq coll) { - return StreamSupport.stream(new StepsAnyIndexedSeq(coll, 0, coll.length()), false); - } - - /** - * Generates a Stream that traverses the keys of a scala.collection.immutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashMap to traverse - * @return A Stream view of the collection which, by default, executes sequentially. - */ - public static Stream streamKeys(scala.collection.immutable.HashMap coll) { - return StreamSupport.stream(new StepsAnyImmHashMapKey(coll, 0, coll.size()), false); - } - - /** - * Generates a Stream that traverses the values of a scala.collection.immutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashMap to traverse - * @return A Stream view of the collection which, by default, executes sequentially. - */ - public static Stream streamValues(scala.collection.immutable.HashMap coll) { - return StreamSupport.stream(new StepsAnyImmHashMapValue(coll, 0, coll.size()), false); - } - - /** - * Generates a Stream that traverses the key-value pairs of a scala.collection.immutable.HashMap. - * The key-value pairs are presented as instances of scala.Tuple2. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashMap to traverse - * @return A Stream view of the collection which, by default, executes sequentially. - */ - public static Stream< scala.Tuple2 > stream(scala.collection.immutable.HashMap coll) { - return StreamSupport.stream(new StepsAnyImmHashMap(coll, 0, coll.size()), false); - } - - /** - * Generates a Stream that traverses a scala.collection.immutable.HashSet. + * Generates a Stream that traverses a Scala collection. *

- * Both sequential and parallel operations will be efficient. + * Parallel processing is only efficient for collections that have a Stepper implementation + * which supports efficient splitting. For collections where this is the case, the stepper + * method has a return type marked with EfficientSplit. * - * @param coll The immutable.HashSet to traverse + * @param coll The IterableOnce to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream stream(scala.collection.immutable.HashSet coll) { - return StreamSupport.stream(new StepsAnyImmHashSet(coll.iterator(), coll.size()), false); - } - - /** - * Generates a Stream that traverses the keys of a scala.collection.mutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The mutable.HashMap to traverse - * @return A Stream view of the collection which, by default, executes sequentially. - */ - public static Stream streamKeys(scala.collection.mutable.HashMap coll) { - scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.stream(new StepsAnyHashTableKey(tbl, 0, tbl.length), false); - } - - /** - * Generates a Stream that traverses the values of a scala.collection.mutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The mutable.HashMap to traverse - * @return A Stream view of the collection which, by default, executes sequentially. - */ - public static Stream streamValues(scala.collection.mutable.HashMap coll) { - scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.stream(new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length), false); - } - - /** - * Generates a Stream that traverses the key-value pairs of a scala.collection.mutable.HashMap. - * The key-value pairs are presented as instances of scala.Tuple2. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The mutable.HashMap to traverse - * @return A Stream view of the collection which, by default, executes sequentially. - */ - public static Stream< scala.Tuple2 > stream(scala.collection.mutable.HashMap coll) { - scala.collection.mutable.HashEntry< K, scala.collection.mutable.DefaultEntry >[] tbl = - CollectionInternals.getTable(coll); - return StreamSupport.stream(new StepsAnyDefaultHashTable(tbl, 0, tbl.length), false); - } - - /** - * Generates a Stream that traverses a scala.collection.mutable.HashSet. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The mutable.HashSet to traverse - * @return A Stream view of the collection which, by default, executes sequentially. - */ - public static Stream stream(scala.collection.mutable.HashSet coll) { - Object[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.stream(new StepsAnyFlatHashTable(tbl, 0, tbl.length), false); - } - - /** - * Generates a Stream that traverses a scala.collection.immutable.Vector. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The Vector to traverse - * @return A Stream view of the collection which, by default, executes sequentially. - */ - public static Stream stream(scala.collection.immutable.Vector coll) { - return StreamSupport.stream(new StepsAnyVector(coll, 0, coll.length()), false); + public static Stream stream(IterableOnce coll) { + return StreamConverters.asJavaSeqStream(coll); } /** * Generates a Stream that traverses the keys of a scala.collection.Map. *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the streamAccumulatedKeys method instead, but - * note that this creates a new collection containing the Map's keys. + * Parallel processing is only efficient for Maps that have a keyStepper implementation + * which supports efficient splitting. For collections where this is the case, the keyStepper + * method has a return type marked with EfficientSplit. * * @param coll The Map to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream streamKeys(scala.collection.Map coll) { - return StreamSupport.stream(new StepsAnyIterator(coll.keysIterator()), false); + public static Stream streamKeys(Map coll) { + return StreamSupport.stream(coll.keyStepper(StepperShape.anyStepperShape()).spliterator(), false); } /** * Generates a Stream that traverses the values of a scala.collection.Map. *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the streamAccumulatedValues method instead, but - * note that this creates a new collection containing the Map's values. + * Parallel processing is only efficient for Maps that have a valueStepper implementation + * which supports efficient splitting. For collections where this is the case, the valueStepper + * method has a return type marked with EfficientSplit. * * @param coll The Map to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream streamValues(scala.collection.Map coll) { - return StreamSupport.stream(new StepsAnyIterator(coll.valuesIterator()), false); + public static Stream streamValues(Map coll) { + return StreamSupport.stream(coll.>valueStepper(StepperShape.anyStepperShape()).spliterator(), false); } /** * Generates a Stream that traverses the key-value pairs of a scala.collection.Map. *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the streamAccumulated method instead, but - * note that this creates a new collection containing the Map's key-value pairs. + * Parallel processing is only efficient for collections that have a Stepper implementation + * which supports efficient splitting. For collections where this is the case, the stepper + * method has a return type marked with EfficientSplit. * * @param coll The Map to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream< scala.Tuple2 > stream(scala.collection.Map coll) { - return StreamSupport.stream(new StepsAnyIterator< scala.Tuple2 >(coll.iterator()), false); + public static Stream< scala.Tuple2 > stream(Map coll) { + return StreamConverters.asJavaSeqStream(coll); } - /** - * Generates a Stream that traverses a scala.collection.Iterator. - *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the streamAccumulated method instead, - * but note that this creates a copy of the contents of the Iterator. - * - * @param coll The scala.collection.Iterator to traverse - * @return A Stream view of the collection which, by default, executes sequentially. - */ - public static Stream stream(scala.collection.Iterator coll) { - return StreamSupport.stream(new StepsAnyIterator(coll), false); - } - - /** - * Generates a Stream that traverses a scala.collection.Iterable. - *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the streamAccumulated method instead, - * but note that this creates a copy of the contents of the Iterable - * - * @param coll The scala.collection.Iterable to traverse - * @return A Stream view of the collection which, by default, executes sequentially. - */ - public static Stream stream(scala.collection.Iterable coll) { - return StreamSupport.stream(new StepsAnyIterator(coll.iterator()), false); - } - - /** + /** * Generates a Stream that traverses any Scala collection by accumulating its entries * into a buffer class (Accumulator). *

@@ -238,9 +97,8 @@ public static Stream stream(scala.collection.Iterable coll) { * @param coll The collection to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream streamAccumulated(scala.collection.TraversableOnce coll) { - scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll); - return StreamSupport.stream(acc.spliterator(), false); + public static Stream streamAccumulated(IterableOnce coll) { + return StreamConverters.asJavaSeqStream(scala.jdk.AnyAccumulator.from(coll)); } /** @@ -252,9 +110,8 @@ public static Stream streamAccumulated(scala.collection.TraversableOnce Stream streamAccumulatedKeys(scala.collection.Map coll) { - scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll.keysIterator()); - return StreamSupport.stream(acc.spliterator(), false); + public static Stream streamAccumulatedKeys(Map coll) { + return StreamConverters.asJavaSeqStream(scala.jdk.AnyAccumulator.from(coll.keysIterator())); } /** @@ -266,662 +123,262 @@ public static Stream streamAccumulatedKeys(scala.collection.Map col * @param coll The map containing values to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream streamAccumulatedValues(scala.collection.Map coll) { - scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll.valuesIterator()); - return StreamSupport.stream(acc.spliterator(), false); + public static Stream streamAccumulatedValues(Map coll) { + return StreamConverters.asJavaSeqStream(scala.jdk.AnyAccumulator.from(coll.valuesIterator())); } //////////////////// // Double Streams // //////////////////// - /** - * Generates a DoubleStream that traverses an IndexedSeq of Doubles. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The IndexedSeq to traverse - * @return A DoubleStream view of the collection which, by default, executes sequentially. - */ - public static DoubleStream doubleStream(scala.collection.IndexedSeq coll) { - return StreamSupport.doubleStream(new StepsDoubleIndexedSeq(coll, 0, coll.length()), false); - } - - /** - * Generates a DoubleStream that traverses double-valued keys of a scala.collection.immutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashMap to traverse - * @return A DoubleStream view of the collection which, by default, executes sequentially. - */ - public static DoubleStream doubleStreamKeys(scala.collection.immutable.HashMap coll) { - return StreamSupport.doubleStream(new StepsDoubleImmHashMapKey(coll, 0, coll.size()), false); - } - - /** - * Generates a DoubleStream that traverses double-valued values of a scala.collection.immutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashMap to traverse - * @return A DoubleStream view of the collection which, by default, executes sequentially. - */ - public static DoubleStream doubleStreamValues(scala.collection.immutable.HashMap coll) { - return StreamSupport.doubleStream(new StepsDoubleImmHashMapValue(coll, 0, coll.size()), false); - } - - /** - * Generates a DoubleStream that traverses a scala.collection.immutable.HashSet of Doubles. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashSet to traverse - * @return A DoubleStream view of the collection which, by default, executes sequentially. - */ - public static DoubleStream doubleStream(scala.collection.immutable.HashSet coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); - return StreamSupport.doubleStream(new StepsDoubleImmHashSet(iter, coll.size()), false); - } - - /** - * Generates a DoubleStream that traverses double-valued keys of a scala.collection.mutable.HashMap. + /** + * Generates a DoubleStream that traverses a Scala collection. *

- * Both sequential and parallel operations will be efficient. + * Parallel processing is only efficient for collections that have a Stepper implementation + * which supports efficient splitting. For collections where this is the case, the stepper + * method has a return type marked with EfficientSplit. * - * @param coll The mutable.HashMap to traverse + * @param coll The IterableOnce to traverse * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleStreamKeys(scala.collection.mutable.HashMap coll) { - scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.doubleStream(new StepsDoubleHashTableKey(tbl, 0, tbl.length), false); + public static DoubleStream doubleStream(IterableOnce coll) { + return StreamConverters.asJavaSeqDoubleStream(coll); } - /** - * Generates a DoubleStream that traverses double-valued values of a scala.collection.mutable.HashMap. + /** + * Generates a DoubleStream that traverses the keys of a scala.collection.Map. *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The mutable.HashMap to traverse - * @return A DoubleStream view of the collection which, by default, executes sequentially. - */ - public static DoubleStream doubleStreamValues(scala.collection.mutable.HashMap coll) { - scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.doubleStream(new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length), false); - } - - /** - * Generates a DoubleStream that traverses a scala.collection.mutable.HashSet of Doubles. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The mutable.HashSet to traverse - * @return A DoubleStream view of the collection which, by default, executes sequentially. - */ - public static DoubleStream doubleStream(scala.collection.mutable.HashSet coll) { - Object[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.doubleStream(new StepsDoubleFlatHashTable(tbl, 0, tbl.length), false); - } - - /** - * Generates a DoubleStream that traverses a scala.collection.immutable.Vector of Doubles. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The Vector to traverse - * @return A DoubleStream view of the collection which, by default, executes sequentially. - */ - public static DoubleStream doubleStream(scala.collection.immutable.Vector coll) { - scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; - return StreamSupport.doubleStream(new StepsDoubleVector(erased, 0, coll.length()), false); - } - - /** - * Generates a DoubleStream that traverses the double-valued keys of a scala.collection.Map. - *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the doubleStreamAccumulatedKeys method instead, but - * note that this creates a new collection containing the Map's keys. + * Parallel processing is only efficient for Maps that have a keyStepper implementation + * which supports efficient splitting. For collections where this is the case, the keyStepper + * method has a return type marked with EfficientSplit. * * @param coll The Map to traverse * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleStreamKeys(scala.collection.Map coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); - return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); + public static DoubleStream doubleStreamKeys(Map coll) { + return StreamSupport.doubleStream(coll.keyStepper((StepperShape)(Object)StepperShape.doubleStepperShape()).spliterator(), false); } - /** - * Generates a DoubleStream that traverses the double-valued values of a scala.collection.Map. + /** + * Generates a DoubleStream that traverses the values of a scala.collection.Map. *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the doubleStreamAccumulatedValues method instead, but - * note that this creates a new collection containing the Map's values. + * Parallel processing is only efficient for Maps that have a valueStepper implementation + * which supports efficient splitting. For collections where this is the case, the valueStepper + * method has a return type marked with EfficientSplit. * * @param coll The Map to traverse * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleStreamValues(scala.collection.Map coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); - return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); + public static DoubleStream doubleStreamValues(Map coll) { + return StreamSupport.doubleStream(coll.valueStepper((StepperShape)(Object)StepperShape.doubleStepperShape()).spliterator(), false); } - /** - * Generates a DoubleStream that traverses a double-valued scala.collection.Iterator. - *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the doubleStreamAccumulated method instead, - * but note that this creates a copy of the contents of the Iterator. - * - * @param coll The scala.collection.Iterator to traverse - * @return A DoubleStream view of the collection which, by default, executes sequentially. - */ - public static DoubleStream doubleStream(scala.collection.Iterator coll) { - return StreamSupport.doubleStream(new StepsDoubleIterator((scala.collection.Iterator)coll), false); - } - - /** - * Generates a DoubleStream that traverses a double-valued scala.collection.Iterable. - *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the doubleStreamAccumulated method instead, - * but note that this creates a copy of the contents of the Iterable. - * - * @param coll The scala.collection.Iterable to traverse - * @return A DoubleStream view of the collection which, by default, executes sequentially. - */ - public static DoubleStream doubleStream(scala.collection.Iterable coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); - return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); - } - - /** - * Generates a Stream that traverses any Scala collection by accumulating its entries + /** + * Generates a DoubleStream that traverses any Scala collection by accumulating its entries * into a buffer class (Accumulator). *

* Both sequential and parallel operations will be efficient. * * @param coll The collection to traverse - * @return A Stream view of the collection which, by default, executes sequentially. + * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleStreamAccumulated(scala.collection.TraversableOnce coll) { - scala.compat.java8.collectionImpl.DoubleAccumulator acc = - scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.TraversableOnce)coll); - return StreamSupport.doubleStream(acc.spliterator(), false); + public static DoubleStream doubleStreamAccumulated(IterableOnce coll) { + return StreamConverters.asJavaSeqDoubleStream(coll); } - /** - * Generates a Stream that traverses the keys of any Scala map by + /** + * Generates a DoubleStream that traverses the keys of any Scala map by * accumulating those keys into a buffer class (Accumulator). *

* Both sequential and parallel operations will be efficient. * * @param coll The map containing keys to traverse - * @return A Stream view of the collection which, by default, executes sequentially. + * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleStreamAccumulatedKeys(scala.collection.Map coll) { - scala.compat.java8.collectionImpl.DoubleAccumulator acc = - scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.Iterator)coll.keysIterator()); - return StreamSupport.doubleStream(acc.spliterator(), false); + public static DoubleStream doubleStreamAccumulatedKeys(Map coll) { + return StreamConverters.asJavaSeqDoubleStream(coll.keysIterator()); } - /** - * Generates a Stream that traverses the values of any Scala map by + /** + * Generates a DoubleStream that traverses the values of any Scala map by * accumulating those values into a buffer class (Accumulator). *

* Both sequential and parallel operations will be efficient. * * @param coll The map containing values to traverse - * @return A Stream view of the collection which, by default, executes sequentially. + * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleStreamAccumulatedValues(scala.collection.Map coll) { - scala.compat.java8.collectionImpl.DoubleAccumulator acc = - scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); - return StreamSupport.doubleStream(acc.spliterator(), false); + public static DoubleStream doubleStreamAccumulatedValues(Map coll) { + return StreamConverters.asJavaSeqDoubleStream(coll.valuesIterator()); } ///////////////// // Int Streams // ///////////////// - /** - * Generates a IntStream that traverses a BitSet. + /** + * Generates a IntStream that traverses a Scala collection. *

- * Both sequential and parallel operations will be efficient. + * Parallel processing is only efficient for collections that have a Stepper implementation + * which supports efficient splitting. For collections where this is the case, the stepper + * method has a return type marked with EfficientSplit. * - * @param coll The BitSet to traverse + * @param coll The IterableOnce to traverse * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intStream(scala.collection.BitSet coll) { - // Let the value class figure out the casting! - scala.compat.java8.converterImpl.RichBitSetCanStep rbscs = - new scala.compat.java8.converterImpl.RichBitSetCanStep(coll); - return StreamSupport.intStream(rbscs.stepper(StepperShape$.MODULE$.intStepperShape()), false); + public static IntStream intStream(IterableOnce coll) { + return StreamConverters.asJavaSeqIntStream(coll); } - /** - * Generates a IntStream that traverses a Range. + /** + * Generates a IntStream that traverses the keys of a scala.collection.Map. *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The Range to traverse - * @return A IntStream view of the collection which, by default, executes sequentially. - */ - public static IntStream intStream(scala.collection.immutable.Range coll) { - return StreamSupport.intStream(new scala.compat.java8.converterImpl.StepsIntRange(coll, 0, coll.length()), false); - } - - /** - * Generates a IntStream that traverses an IndexedSeq of Ints. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The IndexedSeq to traverse - * @return A IntStream view of the collection which, by default, executes sequentially. - */ - public static IntStream intStream(scala.collection.IndexedSeq coll) { - return StreamSupport.intStream(new StepsIntIndexedSeq(coll, 0, coll.length()), false); - } - - /** - * Generates a IntStream that traverses int-valued keys of a scala.collection.immutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashMap to traverse - * @return A IntStream view of the collection which, by default, executes sequentially. - */ - public static IntStream intStreamKeys(scala.collection.immutable.HashMap coll) { - return StreamSupport.intStream(new StepsIntImmHashMapKey(coll, 0, coll.size()), false); - } - - /** - * Generates a IntStream that traverses int-valued values of a scala.collection.immutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashMap to traverse - * @return A IntStream view of the collection which, by default, executes sequentially. - */ - public static IntStream intStreamValues(scala.collection.immutable.HashMap coll) { - return StreamSupport.intStream(new StepsIntImmHashMapValue(coll, 0, coll.size()), false); - } - - /** - * Generates a IntStream that traverses a scala.collection.immutable.HashSet of Ints. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashSet to traverse - * @return A IntStream view of the collection which, by default, executes sequentially. - */ - public static IntStream intStream(scala.collection.immutable.HashSet coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); - return StreamSupport.intStream(new StepsIntImmHashSet(iter, coll.size()), false); - } - - /** - * Generates a IntStream that traverses int-valued keys of a scala.collection.mutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The mutable.HashMap to traverse - * @return A IntStream view of the collection which, by default, executes sequentially. - */ - public static IntStream intStreamKeys(scala.collection.mutable.HashMap coll) { - scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.intStream(new StepsIntHashTableKey(tbl, 0, tbl.length), false); - } - - /** - * Generates a IntStream that traverses int-valued values of a scala.collection.mutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The mutable.HashMap to traverse - * @return A IntStream view of the collection which, by default, executes sequentially. - */ - public static IntStream intStreamValues(scala.collection.mutable.HashMap coll) { - scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.intStream(new StepsIntDefaultHashTableValue(tbl, 0, tbl.length), false); - } - - /** - * Generates a IntStream that traverses a scala.collection.mutable.HashSet of Ints. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The mutable.HashSet to traverse - * @return A IntStream view of the collection which, by default, executes sequentially. - */ - public static IntStream intStream(scala.collection.mutable.HashSet coll) { - Object[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.intStream(new StepsIntFlatHashTable(tbl, 0, tbl.length), false); - } - - /** - * Generates a IntStream that traverses a scala.collection.immutable.Vector of Ints. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The Vector to traverse - * @return A IntStream view of the collection which, by default, executes sequentially. - */ - public static IntStream intStream(scala.collection.immutable.Vector coll) { - scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; - return StreamSupport.intStream(new StepsIntVector(erased, 0, coll.length()), false); - } - - /** - * Generates a IntStream that traverses the int-valued keys of a scala.collection.Map. - *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the intStreamAccumulatedKeys method instead, but - * note that this creates a new collection containing the Map's keys. + * Parallel processing is only efficient for Maps that have a keyStepper implementation + * which supports efficient splitting. For collections where this is the case, the keyStepper + * method has a return type marked with EfficientSplit. * * @param coll The Map to traverse * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intStreamKeys(scala.collection.Map coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); - return StreamSupport.intStream(new StepsIntIterator(iter), false); + public static IntStream intStreamKeys(Map coll) { + return StreamSupport.intStream(coll.keyStepper((StepperShape)(Object)StepperShape.intStepperShape()).spliterator(), false); } - /** - * Generates a IntStream that traverses the int-valued values of a scala.collection.Map. + /** + * Generates a IntStream that traverses the values of a scala.collection.Map. *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the intStreamAccumulatedValues method instead, but - * note that this creates a new collection containing the Map's values. + * Parallel processing is only efficient for Maps that have a valueStepper implementation + * which supports efficient splitting. For collections where this is the case, the valueStepper + * method has a return type marked with EfficientSplit. * * @param coll The Map to traverse * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intStreamValues(scala.collection.Map coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); - return StreamSupport.intStream(new StepsIntIterator(iter), false); + public static IntStream intStreamValues(Map coll) { + return StreamSupport.intStream(coll.valueStepper((StepperShape)(Object)StepperShape.intStepperShape()).spliterator(), false); } - /** - * Generates a IntStream that traverses a int-valued scala.collection.Iterator. - *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the intStreamAccumulated method instead, - * but note that this creates a copy of the contents of the Iterator. - * - * @param coll The scala.collection.Iterator to traverse - * @return A IntStream view of the collection which, by default, executes sequentially. - */ - public static IntStream intStream(scala.collection.Iterator coll) { - return StreamSupport.intStream(new StepsIntIterator((scala.collection.Iterator)coll), false); - } - - /** - * Generates a IntStream that traverses a int-valued scala.collection.Iterable. - *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the intStreamAccumulated method instead, - * but note that this creates a copy of the contents of the Iterable. - * - * @param coll The scala.collection.Iterable to traverse - * @return A IntStream view of the collection which, by default, executes sequentially. - */ - public static IntStream intStream(scala.collection.Iterable coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); - return StreamSupport.intStream(new StepsIntIterator(iter), false); - } - - /** - * Generates a Stream that traverses any Scala collection by accumulating its entries + /** + * Generates a IntStream that traverses any Scala collection by accumulating its entries * into a buffer class (Accumulator). *

* Both sequential and parallel operations will be efficient. * * @param coll The collection to traverse - * @return A Stream view of the collection which, by default, executes sequentially. + * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intStreamAccumulated(scala.collection.TraversableOnce coll) { - scala.compat.java8.collectionImpl.IntAccumulator acc = - scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.TraversableOnce)coll); - return StreamSupport.intStream(acc.spliterator(), false); + public static IntStream intStreamAccumulated(IterableOnce coll) { + return StreamConverters.asJavaSeqIntStream(coll); } - /** - * Generates a Stream that traverses the keys of any Scala map by + /** + * Generates a IntStream that traverses the keys of any Scala map by * accumulating those keys into a buffer class (Accumulator). *

* Both sequential and parallel operations will be efficient. * * @param coll The map containing keys to traverse - * @return A Stream view of the collection which, by default, executes sequentially. + * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intStreamAccumulatedKeys(scala.collection.Map coll) { - scala.compat.java8.collectionImpl.IntAccumulator acc = - scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.Iterator)coll.keysIterator()); - return StreamSupport.intStream(acc.spliterator(), false); + public static IntStream intStreamAccumulatedKeys(Map coll) { + return StreamConverters.asJavaSeqIntStream(coll.keysIterator()); } - /** - * Generates a Stream that traverses the values of any Scala map by + /** + * Generates a IntStream that traverses the values of any Scala map by * accumulating those values into a buffer class (Accumulator). *

* Both sequential and parallel operations will be efficient. * * @param coll The map containing values to traverse - * @return A Stream view of the collection which, by default, executes sequentially. + * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intStreamAccumulatedValues(scala.collection.Map coll) { - scala.compat.java8.collectionImpl.IntAccumulator acc = - scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); - return StreamSupport.intStream(acc.spliterator(), false); + public static IntStream intStreamAccumulatedValues(Map coll) { + return StreamConverters.asJavaSeqIntStream(coll.valuesIterator()); } ////////////////// // Long Streams // ////////////////// - /** - * Generates a LongStream that traverses an IndexedSeq of Longs. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The IndexedSeq to traverse - * @return A LongStream view of the collection which, by default, executes sequentially. - */ - public static LongStream longStream(scala.collection.IndexedSeq coll) { - return StreamSupport.longStream(new StepsLongIndexedSeq(coll, 0, coll.length()), false); - } - - /** - * Generates a LongStream that traverses long-valued keys of a scala.collection.immutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashMap to traverse - * @return A LongStream view of the collection which, by default, executes sequentially. - */ - public static LongStream longStreamKeys(scala.collection.immutable.HashMap coll) { - return StreamSupport.longStream(new StepsLongImmHashMapKey(coll, 0, coll.size()), false); - } - - /** - * Generates a LongStream that traverses long-valued values of a scala.collection.immutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashMap to traverse - * @return A LongStream view of the collection which, by default, executes sequentially. - */ - public static LongStream longStreamValues(scala.collection.immutable.HashMap coll) { - return StreamSupport.longStream(new StepsLongImmHashMapValue(coll, 0, coll.size()), false); - } - - /** - * Generates a LongStream that traverses a scala.collection.immutable.HashSet of Longs. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The immutable.HashSet to traverse - * @return A LongStream view of the collection which, by default, executes sequentially. - */ - public static LongStream longStream(scala.collection.immutable.HashSet coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); - return StreamSupport.longStream(new StepsLongImmHashSet(iter, coll.size()), false); - } - - /** - * Generates a LongStream that traverses long-valued keys of a scala.collection.mutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The mutable.HashMap to traverse - * @return A LongStream view of the collection which, by default, executes sequentially. - */ - public static LongStream longStreamKeys(scala.collection.mutable.HashMap coll) { - scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.longStream(new StepsLongHashTableKey(tbl, 0, tbl.length), false); - } - - /** - * Generates a LongStream that traverses long-valued values of a scala.collection.mutable.HashMap. - *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The mutable.HashMap to traverse - * @return A LongStream view of the collection which, by default, executes sequentially. - */ - public static LongStream longStreamValues(scala.collection.mutable.HashMap coll) { - scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.longStream(new StepsLongDefaultHashTableValue(tbl, 0, tbl.length), false); - } - - /** - * Generates a LongStream that traverses a scala.collection.mutable.HashSet of Longs. + /** + * Generates a LongStream that traverses a Scala collection. *

- * Both sequential and parallel operations will be efficient. + * Parallel processing is only efficient for collections that have a Stepper implementation + * which supports efficient splitting. For collections where this is the case, the stepper + * method has a return type marked with EfficientSplit. * - * @param coll The mutable.HashSet to traverse + * @param coll The IterableOnce to traverse * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longStream(scala.collection.mutable.HashSet coll) { - Object[] tbl = CollectionInternals.getTable(coll); - return StreamSupport.longStream(new StepsLongFlatHashTable(tbl, 0, tbl.length), false); + public static LongStream longStream(IterableOnce coll) { + return StreamConverters.asJavaSeqLongStream(coll); } - /** - * Generates a LongStream that traverses a scala.collection.immutable.Vector of Longs. + /** + * Generates a LongStream that traverses the keys of a scala.collection.Map. *

- * Both sequential and parallel operations will be efficient. - * - * @param coll The Vector to traverse - * @return A LongStream view of the collection which, by default, executes sequentially. - */ - public static LongStream longStream(scala.collection.immutable.Vector coll) { - scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; - return StreamSupport.longStream(new StepsLongVector(erased, 0, coll.length()), false); - } - - /** - * Generates a LongStream that traverses the long-valued keys of a scala.collection.Map. - *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the longStreamAccumulatedKeys method instead, but - * note that this creates a new collection containing the Map's keys. + * Parallel processing is only efficient for Maps that have a keyStepper implementation + * which supports efficient splitting. For collections where this is the case, the keyStepper + * method has a return type marked with EfficientSplit. * * @param coll The Map to traverse * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longStreamKeys(scala.collection.Map coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); - return StreamSupport.longStream(new StepsLongIterator(iter), false); + public static LongStream longStreamKeys(Map coll) { + return StreamSupport.longStream(coll.keyStepper((StepperShape)(Object)StepperShape.doubleStepperShape()).spliterator(), false); } - /** - * Generates a LongStream that traverses the long-valued values of a scala.collection.Map. + /** + * Generates a LongStream that traverses the values of a scala.collection.Map. *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the longStreamAccumulatedValues method instead, but - * note that this creates a new collection containing the Map's values. + * Parallel processing is only efficient for Maps that have a valueStepper implementation + * which supports efficient splitting. For collections where this is the case, the valueStepper + * method has a return type marked with EfficientSplit. * * @param coll The Map to traverse * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longStreamValues(scala.collection.Map coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); - return StreamSupport.longStream(new StepsLongIterator(iter), false); + public static LongStream longStreamValues(Map coll) { + return StreamSupport.longStream(coll.valueStepper((StepperShape)(Object)StepperShape.doubleStepperShape()).spliterator(), false); } - /** - * Generates a LongStream that traverses a long-valued scala.collection.Iterator. - *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the longStreamAccumulated method instead, - * but note that this creates a copy of the contents of the Iterator. - * - * @param coll The scala.collection.Iterator to traverse - * @return A LongStream view of the collection which, by default, executes sequentially. - */ - public static LongStream longStream(scala.collection.Iterator coll) { - return StreamSupport.longStream(new StepsLongIterator((scala.collection.Iterator)coll), false); - } - - /** - * Generates a LongStream that traverses a long-valued scala.collection.Iterable. - *

- * Only sequential operations will be efficient. - * For efficient parallel operation, use the longStreamAccumulated method instead, - * but note that this creates a copy of the contents of the Iterable. - * - * @param coll The scala.collection.Iterable to traverse - * @return A LongStream view of the collection which, by default, executes sequentially. - */ - public static LongStream longStream(scala.collection.Iterable coll) { - scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); - return StreamSupport.longStream(new StepsLongIterator(iter), false); - } - - /** - * Generates a Stream that traverses any Scala collection by accumulating its entries + /** + * Generates a LongStream that traverses any Scala collection by accumulating its entries * into a buffer class (Accumulator). *

* Both sequential and parallel operations will be efficient. * * @param coll The collection to traverse - * @return A Stream view of the collection which, by default, executes sequentially. + * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longStreamAccumulated(scala.collection.TraversableOnce coll) { - scala.compat.java8.collectionImpl.LongAccumulator acc = - scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.TraversableOnce)coll); - return StreamSupport.longStream(acc.spliterator(), false); + public static LongStream longStreamAccumulated(IterableOnce coll) { + return StreamConverters.asJavaSeqLongStream(coll); } - /** - * Generates a Stream that traverses the keys of any Scala map by + /** + * Generates a LongStream that traverses the keys of any Scala map by * accumulating those keys into a buffer class (Accumulator). *

* Both sequential and parallel operations will be efficient. * * @param coll The map containing keys to traverse - * @return A Stream view of the collection which, by default, executes sequentially. + * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longStreamAccumulatedKeys(scala.collection.Map coll) { - scala.compat.java8.collectionImpl.LongAccumulator acc = - scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.Iterator)coll.keysIterator()); - return StreamSupport.longStream(acc.spliterator(), false); + public static LongStream longStreamAccumulatedKeys(Map coll) { + return StreamConverters.asJavaSeqLongStream(coll.keysIterator()); } - /** - * Generates a Stream that traverses the values of any Scala map by + /** + * Generates a LongStream that traverses the values of any Scala map by * accumulating those values into a buffer class (Accumulator). *

* Both sequential and parallel operations will be efficient. * * @param coll The map containing values to traverse - * @return A Stream view of the collection which, by default, executes sequentially. + * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longStreamAccumulatedValues(scala.collection.Map coll) { - scala.compat.java8.collectionImpl.LongAccumulator acc = - scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); - return StreamSupport.longStream(acc.spliterator(), false); + public static LongStream longStreamAccumulatedValues(Map coll) { + return StreamConverters.asJavaSeqLongStream(coll.valuesIterator()); } } diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java deleted file mode 100644 index 473de11..0000000 --- a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.runtime; - -// No imports! All type names are fully qualified to avoid confusion! - -public class CollectionInternals { - public static Object[] getTable(scala.collection.mutable.FlatHashTable fht) { return fht.hashTableContents().table(); } - public static > scala.collection.mutable.HashEntry[] getTable(scala.collection.mutable.HashTable ht) { return ht.hashTableContents().table(); } - public static boolean getDirt(scala.collection.immutable.Vector v) { return v.dirty(); } - public static Object[] getDisplay0(scala.collection.immutable.Vector v) { return v.display0(); } - public static Object[] getDisplay0(scala.collection.immutable.VectorIterator p) { return p.display0(); } - public static Object[] getDisplay1(scala.collection.immutable.Vector v) { return v.display1(); } - public static Object[] getDisplay1(scala.collection.immutable.VectorIterator p) { return p.display1(); } - public static Object[] getDisplay2(scala.collection.immutable.Vector v) { return v.display2(); } - public static Object[] getDisplay2(scala.collection.immutable.VectorIterator p) { return p.display2(); } - public static Object[] getDisplay3(scala.collection.immutable.Vector v) { return v.display3(); } - public static Object[] getDisplay3(scala.collection.immutable.VectorIterator p) { return p.display3(); } - public static Object[] getDisplay4(scala.collection.immutable.Vector v) { return v.display4(); } - public static Object[] getDisplay4(scala.collection.immutable.VectorIterator p) { return p.display4(); } - public static Object[] getDisplay5(scala.collection.immutable.Vector v) { return v.display5(); } - public static Object[] getDisplay5(scala.collection.immutable.VectorIterator p) { return p.display5(); } - public static scala.Tuple2< scala.Tuple2< scala.collection.Iterator, Object >, scala.collection.Iterator > trieIteratorSplit(scala.collection.Iterator it) { - if (it instanceof scala.collection.immutable.TrieIterator) { - scala.collection.immutable.TrieIterator trie = (scala.collection.immutable.TrieIterator)it; - return trie.split(); - } - return null; - } - public static long[] getBitSetInternals(scala.collection.mutable.BitSet bitSet) { return bitSet.elems(); } -} - diff --git a/src/main/scala/scala/compat/java8/FutureConverters.scala b/src/main/scala/scala/compat/java8/FutureConverters.scala index 341f400..a0a9c6c 100644 --- a/src/main/scala/scala/compat/java8/FutureConverters.scala +++ b/src/main/scala/scala/compat/java8/FutureConverters.scala @@ -68,7 +68,7 @@ object FutureConverters { case p: P[T] => p.wrapped case _ => val cf = new CF[T](f) - implicit val ec = InternalCallbackExecutor + implicit val ec = ExecutionContext.parasitic f onComplete cf cf } diff --git a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala index 2d80ba6..d0abb4d 100644 --- a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala +++ b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala @@ -53,10 +53,10 @@ object PrimitiveIteratorConverters { def nextDouble() = it.next() override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } override def forEachRemaining(c: java.util.function.DoubleConsumer): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } } } @@ -74,10 +74,10 @@ object PrimitiveIteratorConverters { def nextInt() = it.next() override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } override def forEachRemaining(c: java.util.function.IntConsumer): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } } } @@ -95,10 +95,10 @@ object PrimitiveIteratorConverters { def nextLong() = it.next() override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } override def forEachRemaining(c: java.util.function.LongConsumer): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } } } diff --git a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala deleted file mode 100644 index 36838f3..0000000 --- a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8 - -import language.implicitConversions - -import java.util._ -import scala.compat.java8.collectionImpl._ - -package SpliteratorConverters { - class SpliteratorToStepper[A] private[java8] (private val underlying: Spliterator[A]) extends AnyVal { - def stepper: AnyStepper[A] = Stepper.ofSpliterator(underlying) - } - - trait Priority2SpliteratorConverters { - implicit def spliteratorToStepper[A](sp: Spliterator[A]) = new SpliteratorToStepper[A](sp) - } -} - - -package object SpliteratorConverters extends SpliteratorConverters.Priority2SpliteratorConverters { - implicit final class SpliteratorOfDoubleToStepper(private val underlying: Spliterator.OfDouble) extends AnyVal { - def stepper: DoubleStepper = Stepper.ofSpliterator(underlying) - } - implicit final class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal { - def stepper: IntStepper = Stepper.ofSpliterator(underlying) - } - implicit final class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal { - def stepper: LongStepper = Stepper.ofSpliterator(underlying) - } -} diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 00a3d24..55e8bc9 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -12,112 +12,350 @@ package scala.compat.java8 -import scala.language.higherKinds - import java.util.stream._ -import scala.compat.java8.collectionImpl._ + +import scala.annotation.implicitNotFound +import scala.collection.Stepper.EfficientSplit +import scala.collection.convert.StreamExtensions.{AccumulatorFactoryInfo, StreamShape, StreamUnboxer} +import scala.collection.{IterableOnce, Stepper, StepperShape} import scala.compat.java8.converterImpl._ +import scala.jdk._ +import scala.language.higherKinds +import scala.jdk.CollectionConverters.Ops._ -/** Classes or objects implementing this trait create streams suitable for sequential use */ -trait MakesSequentialStream[T, SS <: java.util.stream.BaseStream[_, SS]] extends Any { - def seqStream: SS -} -/** Classes or objects implementing this trait create streams suitable for parallel use */ -trait MakesParallelStream[T, SS <: java.util.stream.BaseStream[_, SS]] extends Any { - def parStream: SS -} +/** Defines extension methods to create Java Streams for Scala collections, available through + * [[scala.jdk.StreamConverters.Ops]]. + */ +trait StreamExtensions { + implicit def richStepper[A](s: Stepper[A]): StepperExtensions[A] = new StepperExtensions[A](s) -sealed trait StreamShape[T, S <: BaseStream[_, S]] { - def fromStepper (mk: MakesStepper[T, _], par: Boolean): S - def fromKeyStepper (mk: MakesKeyValueStepper[T, _, _], par: Boolean): S - def fromValueStepper(mk: MakesKeyValueStepper[_, T, _], par: Boolean): S -} -object StreamShape extends StreamShapeLowPriority { - // primitive - implicit val IntValue = intStreamShape[Int] - implicit val LongValue = longStreamShape[Long] - implicit val DoubleValue = doubleStreamShape[Double] - - // widening - implicit val ByteValue = intStreamShape[Byte] - implicit val ShortValue = intStreamShape[Short] - implicit val CharValue = intStreamShape[Char] - implicit val FloatValue = doubleStreamShape[Float] -} -trait StreamShapeLowPriority { - protected[this] abstract class BaseStreamShape[T, S <: BaseStream[_, S], St <: Stepper[_]](implicit ss: StepperShape[T, St]) extends StreamShape[T, S] { - final def fromStepper (mk: MakesStepper[T, _], par: Boolean): S = stream(mk.stepper, par) - final def fromKeyStepper (mk: MakesKeyValueStepper[T, _, _], par: Boolean): S = stream(mk.keyStepper, par) - final def fromValueStepper(mk: MakesKeyValueStepper[_, T, _], par: Boolean): S = stream(mk.valueStepper, par) - @inline private[this] def stream(st: St, par: Boolean): S = mkStream(if(par) st.anticipateParallelism else st, par) - protected[this] def mkStream(st: St, par: Boolean): S + // collections + + implicit class IterableHasSeqStream[A](cc: IterableOnce[A]) { + /** Create a sequential [[java.util.stream.Stream Java Stream]] for this collection. If the + * collection contains primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def seqStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[A, S, St], st: StepperShape[A, St]): S = + s.fromStepper(cc.stepper, par = false) } - protected[this] def intStreamShape[T](implicit ss: StepperShape[T, IntStepper]): StreamShape[T, IntStream] = new BaseStreamShape[T, IntStream, IntStepper] { - protected[this] def mkStream(st: IntStepper, par: Boolean): IntStream = StreamSupport.intStream(st, par) + + protected type IterableOnceWithEfficientStepper[A] = IterableOnce[A] { + def stepper[B >: A, S <: Stepper[_]](implicit shape : StepperShape[B, S]) : S with EfficientSplit } - protected[this] def longStreamShape[T](implicit ss: StepperShape[T, LongStepper]): StreamShape[T, LongStream] = new BaseStreamShape[T, LongStream, LongStepper] { - protected[this] def mkStream(st: LongStepper, par: Boolean): LongStream = StreamSupport.longStream(st, par) + + // Not `CC[X] <: IterableOnce[X]`, but `C` with an extra constraint, to support non-parametric classes like IntAccumulator + implicit class IterableNonGenericHasParStream[A, C <: IterableOnce[_]](c: C)(implicit ev: C <:< IterableOnce[A]) { + /** Create a parallel [[java.util.stream.Stream Java Stream]] for this collection. If the + * collection contains primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def parStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit + s: StreamShape[A, S, St], + st: StepperShape[A, St], + @implicitNotFound("`parStream` can only be called on collections where `stepper` returns a `Stepper with EfficientSplit`") + isEfficient: C <:< IterableOnceWithEfficientStepper[A]): S = + s.fromStepper(ev(c).stepper, par = true) } - protected[this] def doubleStreamShape[T](implicit ss: StepperShape[T, DoubleStepper]): StreamShape[T, DoubleStream] = new BaseStreamShape[T, DoubleStream, DoubleStepper] { - protected[this] def mkStream(st: DoubleStepper, par: Boolean): DoubleStream = StreamSupport.doubleStream(st, par) + + // maps + + implicit class MapHasSeqKeyValueStream[K, V, CC[X, Y] <: collection.MapOps[X, Y, CC, _]](cc: CC[K, V]) { + /** Create a sequential [[java.util.stream.Stream Java Stream]] for the keys of this map. If + * the keys are primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def seqKeyStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[K, S, St], st: StepperShape[K, St]): S = + s.fromStepper(cc.keyStepper, par = false) + + /** Create a sequential [[java.util.stream.Stream Java Stream]] for the values of this map. If + * the values are primitives, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def seqValueStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[V, S, St], st: StepperShape[V, St]): S = + s.fromStepper(cc.valueStepper, par = false) + + // The seqStream extension method for IterableOnce doesn't apply because its `CC` takes a single type parameter, whereas the one here takes two + /** Create a sequential [[java.util.stream.Stream Java Stream]] for the `(key, value)` pairs of + * this map. + */ + def seqStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[(K, V), S, St], st: StepperShape[(K, V), St]): S = + s.fromStepper(cc.stepper, par = false) } - // reference - implicit def anyStreamShape[T]: StreamShape[T, Stream[T]] = new BaseStreamShape[T, Stream[T], AnyStepper[T]] { - protected[this] def mkStream(st: AnyStepper[T], par: Boolean): Stream[T] = StreamSupport.stream(st, par) + + implicit class MapHasParKeyValueStream[K, V, CC[X, Y] <: collection.MapOps[X, Y, CC, _]](cc: CC[K, V]) { + private type MapOpsWithEfficientKeyStepper[K, V] = collection.MapOps[K, V, CC, _] { def keyStepper[S <: Stepper[_]](implicit shape : StepperShape[K, S]) : S with EfficientSplit } + private type MapOpsWithEfficientValueStepper[K, V] = collection.MapOps[K, V, CC, _] { def valueStepper[V1 >: V, S <: Stepper[_]](implicit shape : StepperShape[V1, S]) : S with EfficientSplit } + private type MapOpsWithEfficientStepper[K, V] = collection.MapOps[K, V, CC, _] { def stepper[B >: (K, V), S <: Stepper[_]](implicit shape : StepperShape[B, S]) : S with EfficientSplit } + + /** Create a parallel [[java.util.stream.Stream Java Stream]] for the keys of this map. If + * the keys are primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def parKeyStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit + s: StreamShape[K, S, St], + st: StepperShape[K, St], + @implicitNotFound("parKeyStream can only be called on maps where `keyStepper` returns a `Stepper with EfficientSplit`") + isEfficient: CC[K, V] <:< MapOpsWithEfficientKeyStepper[K, V]): S = + s.fromStepper(cc.keyStepper, par = true) + + /** Create a parallel [[java.util.stream.Stream Java Stream]] for the values of this map. If + * the values are primitives, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def parValueStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit + s: StreamShape[V, S, St], + st: StepperShape[V, St], + @implicitNotFound("parValueStream can only be called on maps where `valueStepper` returns a `Stepper with EfficientSplit`") + isEfficient: CC[K, V] <:< MapOpsWithEfficientValueStepper[K, V]): S = + s.fromStepper(cc.valueStepper, par = true) + + // The parStream extension method for IterableOnce doesn't apply because its `CC` takes a single type parameter, whereas the one here takes two + /** Create a parallel [[java.util.stream.Stream Java Stream]] for the `(key, value)` pairs of + * this map. + */ + def parStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit + s: StreamShape[(K, V), S, St], + st: StepperShape[(K, V), St], + @implicitNotFound("parStream can only be called on maps where `stepper` returns a `Stepper with EfficientSplit`") + isEfficient: CC[K, V] <:< MapOpsWithEfficientStepper[K, V]): S = + s.fromStepper(cc.stepper, par = true) } -} -trait PrimitiveStreamAccumulator[S, AA] { - def streamAccumulate(stream: S): AA -} + // steppers -trait PrimitiveStreamUnboxer[A, S] { - def apply(boxed: Stream[A]): S -} + implicit class StepperHasSeqStream[A](stepper: Stepper[A]) { + /** Create a sequential [[java.util.stream.Stream Java Stream]] for this stepper. If the + * stepper yields primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def seqStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[A, S, St], st: StepperShape[A, St]): S = + s.fromStepper(stepper.asInstanceOf[St], par = false) + } + + implicit class StepperHasParStream[A](stepper: Stepper[A] with EfficientSplit) { + /** Create a parallel [[java.util.stream.Stream Java Stream]] for this stepper. If the + * stepper yields primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def parStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[A, S, St], st: StepperShape[A, St]): S = + s.fromStepper(stepper.asInstanceOf[St], par = true) + } + + // arrays + // uses the JDK array spliterators (`DoubleArraySpliterator`). users can also call + // `array.stepper.seqStream`, which then uses the Scala steppers (`DoubleArrayStepper`). the + // steppers are also available on byte/short/char/float arrays (`WidenedByteArrayStepper`), + // JDK spliterators only for double/int/long/reference. + + implicit class DoubleArrayHasSeqParStream(a: Array[Double]) { + /** Create a sequential [[java.util.stream.DoubleStream Java DoubleStream]] for this array. */ + def seqStream: DoubleStream = java.util.Arrays.stream(a) + /** Create a parallel [[java.util.stream.DoubleStream Java DoubleStream]] for this array. */ + def parStream: DoubleStream = seqStream.parallel + } -trait Priority2StreamConverters { - implicit class EnrichAnySteppableWithParStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesStepper[A, EfficientSubstep], ss: StreamShape[A, S]) - extends MakesParallelStream[A, S] { - def parStream: S = ss.fromStepper(steppize(cc), true) + implicit class IntArrayHasSeqParStream(a: Array[Int]) { + /** Create a sequential [[java.util.stream.IntStream Java IntStream]] for this array. */ + def seqStream: IntStream = java.util.Arrays.stream(a) + /** Create a parallel [[java.util.stream.IntStream Java IntStream]] for this array. */ + def parStream: IntStream = seqStream.parallel } - implicit class EnrichAnySteppableWithSeqStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesStepper[A, Any], ss: StreamShape[A, S]) - extends MakesSequentialStream[A, S] { - def seqStream: S = ss.fromStepper(steppize(cc), false) + + implicit class LongArrayHasSeqParStream(a: Array[Long]) { + /** Create a sequential [[java.util.stream.LongStream Java LongStream]] for this array. */ + def seqStream: LongStream = java.util.Arrays.stream(a) + /** Create a parallel [[java.util.stream.LongStream Java LongStream]] for this array. */ + def parStream: LongStream = seqStream.parallel } - implicit class EnrichAnySteppableWithParKeyStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesKeyValueStepper[A, _, EfficientSubstep], ss: StreamShape[A, S]) { - def parKeyStream: S = ss.fromKeyStepper(steppize(cc), true) + + implicit class AnyArrayHasSeqParStream[A <: AnyRef](a: Array[A]) { + /** Create a sequential [[java.util.stream.Stream Java Stream]] for this array. */ + def seqStream: Stream[A] = java.util.Arrays.stream(a) + /** Create a parallel [[java.util.stream.Stream Java Stream]] for this array. */ + def parStream: Stream[A] = seqStream.parallel } - implicit class EnrichScalaCollectionWithSeqKeyStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesKeyValueStepper[A, _, Any], ss: StreamShape[A, S]) { - def seqKeyStream: S = ss.fromKeyStepper(steppize(cc), false) + + implicit class ByteArrayHasSeqParStream(a: Array[Byte]) { + /** Create a sequential [[java.util.stream.IntStream Java IntStream]] for this array. */ + def seqStream: IntStream = a.stepper.seqStream + /** Create a parallel [[java.util.stream.IntStream Java IntStream]] for this array. */ + def parStream: IntStream = a.stepper.parStream } - implicit class EnrichAnySteppableWithParValueStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesKeyValueStepper[_, A, EfficientSubstep], ss: StreamShape[A, S]) { - def parValueStream: S = ss.fromValueStepper(steppize(cc), true) + + implicit class ShortArrayHasSeqParStream(a: Array[Short]) { + /** Create a sequential [[java.util.stream.IntStream Java IntStream]] for this array. */ + def seqStream: IntStream = a.stepper.seqStream + /** Create a parallel [[java.util.stream.IntStream Java IntStream]] for this array. */ + def parStream: IntStream = a.stepper.parStream } - implicit class EnrichScalaCollectionWithSeqValueStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesKeyValueStepper[_, A, Any], ss: StreamShape[A, S]) { - def seqValueStream: S = ss.fromValueStepper(steppize(cc), false) + + implicit class CharArrayHasSeqParStream(a: Array[Char]) { + /** Create a sequential [[java.util.stream.IntStream Java IntStream]] for this array. */ + def seqStream: IntStream = a.stepper.seqStream + /** Create a parallel [[java.util.stream.IntStream Java IntStream]] for this array. */ + def parStream: IntStream = a.stepper.parStream + } + + implicit class FloatArrayHasSeqParStream(a: Array[Float]) { + /** Create a sequential [[java.util.stream.DoubleStream Java DoubleStream]] for this array. */ + def seqStream: DoubleStream = a.stepper.seqStream + + /** Create a parallel [[java.util.stream.DoubleStream Java DoubleStream]] for this array. */ + def parStream: DoubleStream = a.stepper.parStream + } + + // toScala for streams + + implicit class StreamHasToScala[A](stream: Stream[A]) { + def accumulate: AnyAccumulator[A] = toScala(Accumulator) + + + /** + * Copy the elements of this stream into a Scala collection. + * + * Converting a parallel streams to an [[Accumulator]] using `stream.toScala(Accumulator)` + * builds the result in parallel. + * + * A `toScala(Accumulator)` call automatically converts streams of boxed integers, longs or + * doubles are converted to the primitive accumulators ([[IntAccumulator]], etc.). + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + def toScala[C1](factory: collection.Factory[A, C1])(implicit info: AccumulatorFactoryInfo[A, C1]): C1 = { + + def anyAcc = stream.collect(AnyAccumulator.supplier[A], AnyAccumulator.adder[A], AnyAccumulator.merger[A]) + if (info.companion == AnyAccumulator) anyAcc.asInstanceOf[C1] + else if (info.companion == IntAccumulator) stream.asInstanceOf[Stream[Int]].collect(IntAccumulator.supplier, IntAccumulator.boxedAdder, IntAccumulator.merger).asInstanceOf[C1] + else if (info.companion == LongAccumulator) stream.asInstanceOf[Stream[Long]].collect(LongAccumulator.supplier, LongAccumulator.boxedAdder, LongAccumulator.merger).asInstanceOf[C1] + else if (info.companion == DoubleAccumulator) stream.asInstanceOf[Stream[Double]].collect(DoubleAccumulator.supplier, DoubleAccumulator.boxedAdder, DoubleAccumulator.merger).asInstanceOf[C1] + else if (stream.isParallel) anyAcc.to(factory) + else factory.fromSpecific(stream.iterator.asScala) + } + + /** Convert a generic Java Stream wrapping a primitive type to a corresponding primitive + * Stream. + */ + def unboxed[S](implicit unboxer: StreamUnboxer[A, S]): S = unboxer(stream) + } + + implicit class StreamIntHasAccumulatePrimitive(s: Stream[Int]) { + def accumulatePrimitive: IntAccumulator = s.toScala(Accumulator) + } + + implicit class StreamLongHasAccumulatePrimitive(s: Stream[Long]) { + def accumulatePrimitive: LongAccumulator = s.toScala(Accumulator) + } + + implicit class StreamDoubleHasAccumulatePrimitive(s: Stream[Double]) { + def accumulatePrimitive: DoubleAccumulator = s.toScala(Accumulator) } -} -trait Priority1StreamConverters extends Priority2StreamConverters { - implicit class RichStream[A](stream: Stream[A]) { - def accumulate = stream.collect(Accumulator.supplier[A], Accumulator.adder[A], Accumulator.merger[A]) - - def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, A, Coll[A]]): Coll[A] = { - if (stream.isParallel) accumulate.to[Coll](cbf) - else { - val b = cbf() - stream.forEachOrdered(new java.util.function.Consumer[A]{ def accept(a: A): Unit = { b += a } }) - b.result() - } + implicit class StreamJIntegerHasAccumulatePrimitive(s: Stream[java.lang.Integer]) { + def accumulatePrimitive: IntAccumulator = s.toScala(Accumulator) + } + + implicit class StreamJLongHasAccumulatePrimitive(s: Stream[java.lang.Long]) { + def accumulatePrimitive: LongAccumulator = s.toScala(Accumulator) + } + + implicit class StreamJDoubleHasAccumulatePrimitive(s: Stream[java.lang.Double]) { + def accumulatePrimitive: DoubleAccumulator = s.toScala(Accumulator) + } + + implicit class IntStreamHasToScala(stream: IntStream) { + def accumulate: IntAccumulator = toScala(IntAccumulator) + + /** + * Copy the elements of this stream into a Scala collection. + * + * Converting a parallel streams to an [[Accumulator]] using `stream.toScala(Accumulator)` + * builds the result in parallel. + * + * A `toScala(Accumulator)` call automatically converts the `IntStream` to a primitive + * [[IntAccumulator]]. + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + def toScala[C1](factory: collection.Factory[Int, C1])(implicit info: AccumulatorFactoryInfo[Int, C1]): C1 = { + def intAcc = stream.collect(IntAccumulator.supplier, IntAccumulator.adder, IntAccumulator.merger) + if (info.companion == AnyAccumulator) stream.collect(AnyAccumulator.supplier[Int], AnyAccumulator.unboxedIntAdder, AnyAccumulator.merger[Int]).asInstanceOf[C1] + else if (info.companion == IntAccumulator) intAcc.asInstanceOf[C1] + else if (stream.isParallel) intAcc.to(factory) + else factory.fromSpecific(stream.iterator.asInstanceOf[java.util.Iterator[Int]].asScala) } - - def unboxed[S](implicit ubx: PrimitiveStreamUnboxer[A, S]): S = ubx(stream) } - - implicit class RichStreamCanAccumulatePrimitive[S](stream: S) { - def accumulatePrimitive[AA](implicit psa: PrimitiveStreamAccumulator[S, AA]) = psa.streamAccumulate(stream) + + implicit class LongStreamHasToScala(stream: LongStream) { + def accumulate: LongAccumulator = toScala(LongAccumulator) + + /** + * Copy the elements of this stream into a Scala collection. + * + * Converting a parallel streams to an [[Accumulator]] using `stream.toScala(Accumulator)` + * builds the result in parallel. + * + * A `toScala(Accumulator)` call automatically converts the `LongStream` to a primitive + * [[LongAccumulator]]. + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + def toScala[C1](factory: collection.Factory[Long, C1])(implicit info: AccumulatorFactoryInfo[Long, C1]): C1 = { + def longAcc = stream.collect(LongAccumulator.supplier, LongAccumulator.adder, LongAccumulator.merger) + if (info.companion == AnyAccumulator) stream.collect(AnyAccumulator.supplier[Long], AnyAccumulator.unboxedLongAdder, AnyAccumulator.merger[Long]).asInstanceOf[C1] + else if (info.companion == LongAccumulator) longAcc.asInstanceOf[C1] + else if (stream.isParallel) longAcc.to(factory) + else factory.fromSpecific(stream.iterator.asInstanceOf[java.util.Iterator[Long]].asScala) + } + } + + implicit class DoubleStreamHasToScala(stream: DoubleStream) { + def accumulate: DoubleAccumulator = toScala(DoubleAccumulator) + + /** + * Copy the elements of this stream into a Scala collection. + * + * Converting a parallel streams to an [[Accumulator]] using `stream.toScala(Accumulator)` + * builds the result in parallel. + * + * A `toScala(Accumulator)` call automatically converts the `DoubleStream` to a primitive + * [[DoubleAccumulator]]. + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + def toScala[C1](factory: collection.Factory[Double, C1])(implicit info: AccumulatorFactoryInfo[Double, C1]): C1 = { + def doubleAcc = stream.collect(DoubleAccumulator.supplier, DoubleAccumulator.adder, DoubleAccumulator.merger) + if (info.companion == AnyAccumulator) stream.collect(AnyAccumulator.supplier[Double], AnyAccumulator.unboxedDoubleAdder, AnyAccumulator.merger[Double]).asInstanceOf[C1] + else if (info.companion == DoubleAccumulator) doubleAcc.asInstanceOf[C1] + else if (stream.isParallel) doubleAcc.to(factory) + else factory.fromSpecific(stream.iterator.asInstanceOf[java.util.Iterator[Double]].asScala) + } } } @@ -185,154 +423,10 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * }}} */ object StreamConverters -extends Priority1StreamConverters -with converterImpl.Priority1StepConverters +extends StreamExtensions with converterImpl.Priority1AccumulatorConverters { - implicit final class EnrichDoubleArrayWithStream(private val a: Array[Double]) - extends AnyVal with MakesSequentialStream[Double, DoubleStream] with MakesParallelStream[Double, DoubleStream] { - def seqStream: DoubleStream = java.util.Arrays.stream(a) - def parStream: DoubleStream = seqStream.parallel - } - - implicit final class EnrichIntArrayWithStream(private val a: Array[Int]) - extends AnyVal with MakesSequentialStream[Int, IntStream] with MakesParallelStream[Int, IntStream] { - def seqStream: IntStream = java.util.Arrays.stream(a) - def parStream: IntStream = seqStream.parallel - } - - implicit final class EnrichLongArrayWithStream(private val a: Array[Long]) - extends AnyVal with MakesSequentialStream[Long, LongStream] with MakesParallelStream[Long, LongStream] { - def seqStream: LongStream = java.util.Arrays.stream(a) - def parStream: LongStream = seqStream.parallel - } - - implicit final class EnrichDoubleWrappedArrayWithStream(private val a: collection.mutable.WrappedArray[Double]) - extends AnyVal with MakesSequentialStream[Double, DoubleStream] with MakesParallelStream[Double, DoubleStream] { - def seqStream: DoubleStream = java.util.Arrays.stream(a.array) - def parStream: DoubleStream = seqStream.parallel - } - - implicit final class EnrichIntWrappedArrayWithStream(private val a: collection.mutable.WrappedArray[Int]) - extends AnyVal with MakesSequentialStream[Int, IntStream] with MakesParallelStream[Int, IntStream] { - def seqStream: IntStream = java.util.Arrays.stream(a.array) - def parStream: IntStream = seqStream.parallel - } - - implicit final class EnrichLongWrappedArrayWithStream(private val a: collection.mutable.WrappedArray[Long]) - extends AnyVal with MakesSequentialStream[Long, LongStream] with MakesParallelStream[Long, LongStream] { - def seqStream: LongStream = java.util.Arrays.stream(a.array) - def parStream: LongStream = seqStream.parallel - } - - implicit val primitiveAccumulateDoubleStream = new PrimitiveStreamAccumulator[Stream[Double], DoubleAccumulator] { - def streamAccumulate(stream: Stream[Double]): DoubleAccumulator = - stream.collect(DoubleAccumulator.supplier, DoubleAccumulator.boxedAdder, DoubleAccumulator.merger) - } - - implicit val primitiveAccumulateDoubleStream2 = - primitiveAccumulateDoubleStream.asInstanceOf[PrimitiveStreamAccumulator[Stream[java.lang.Double], DoubleAccumulator]] - - implicit val primitiveUnboxDoubleStream = new PrimitiveStreamUnboxer[Double, DoubleStream] { - def apply(boxed: Stream[Double]): DoubleStream = - boxed.mapToDouble(new java.util.function.ToDoubleFunction[Double]{ def applyAsDouble(d: Double) = d }) - } - - implicit val primitiveUnboxDoubleStream2 = - primitiveUnboxDoubleStream.asInstanceOf[PrimitiveStreamUnboxer[java.lang.Double, DoubleStream]] - - implicit val primitiveAccumulateIntStream = new PrimitiveStreamAccumulator[Stream[Int], IntAccumulator] { - def streamAccumulate(stream: Stream[Int]): IntAccumulator = - stream.collect(IntAccumulator.supplier, IntAccumulator.boxedAdder, IntAccumulator.merger) - } - - implicit val primitiveAccumulateIntStream2 = - primitiveAccumulateIntStream.asInstanceOf[PrimitiveStreamAccumulator[Stream[java.lang.Integer], IntAccumulator]] - - implicit val primitiveUnboxIntStream = new PrimitiveStreamUnboxer[Int, IntStream] { - def apply(boxed: Stream[Int]): IntStream = - boxed.mapToInt(new java.util.function.ToIntFunction[Int]{ def applyAsInt(d: Int) = d }) - } - - implicit val primitiveUnboxIntStream2 = - primitiveUnboxIntStream.asInstanceOf[PrimitiveStreamUnboxer[java.lang.Integer, IntStream]] - - implicit val primitiveAccumulateLongStream = new PrimitiveStreamAccumulator[Stream[Long], LongAccumulator] { - def streamAccumulate(stream: Stream[Long]): LongAccumulator = - stream.collect(LongAccumulator.supplier, LongAccumulator.boxedAdder, LongAccumulator.merger) - } - - implicit val primitiveAccumulateLongStream2 = - primitiveAccumulateLongStream.asInstanceOf[PrimitiveStreamAccumulator[Stream[java.lang.Long], LongAccumulator]] - - implicit val primitiveUnboxLongStream = new PrimitiveStreamUnboxer[Long, LongStream] { - def apply(boxed: Stream[Long]): LongStream = - boxed.mapToLong(new java.util.function.ToLongFunction[Long]{ def applyAsLong(d: Long) = d }) - } - - implicit val primitiveUnboxLongStream2 = - primitiveUnboxLongStream.asInstanceOf[PrimitiveStreamUnboxer[java.lang.Long, LongStream]] - - implicit final class RichDoubleStream(private val stream: DoubleStream) extends AnyVal { - def accumulate = stream.collect(DoubleAccumulator.supplier, DoubleAccumulator.adder, DoubleAccumulator.merger) - - def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Double, Coll[Double]]): Coll[Double] = { - if (stream.isParallel) accumulate.to[Coll](cbf) - else { - val b = cbf() - stream.forEachOrdered(new java.util.function.DoubleConsumer{ def accept(d: Double): Unit = { b += d } }) - b.result() - } - } - } - - implicit final class RichIntStream(private val stream: IntStream) extends AnyVal { - def accumulate = stream.collect(IntAccumulator.supplier, IntAccumulator.adder, IntAccumulator.merger) - - def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, Coll[Int]]): Coll[Int] = { - if (stream.isParallel) accumulate.to[Coll](cbf) - else { - val b = cbf() - stream.forEachOrdered(new java.util.function.IntConsumer{ def accept(d: Int): Unit = { b += d } }) - b.result() - } - } - } - - implicit final class RichLongStream(private val stream: LongStream) extends AnyVal { - def accumulate = stream.collect(LongAccumulator.supplier, LongAccumulator.adder, LongAccumulator.merger) - - def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Long, Coll[Long]]): Coll[Long] = { - if (stream.isParallel) accumulate.to[Coll](cbf) - else { - val b = cbf() - stream.forEachOrdered(new java.util.function.LongConsumer{ def accept(d: Long): Unit = { b += d } }) - b.result() - } - } - } - - implicit val accumulateDoubleStepper = new AccumulatesFromStepper[Double, DoubleAccumulator] { - def apply(stepper: Stepper[Double]) = { - val a = new DoubleAccumulator - while (stepper.hasStep) a += stepper.nextStep - a - } - } - - implicit val accumulateIntStepper = new AccumulatesFromStepper[Int, IntAccumulator] { - def apply(stepper: Stepper[Int]) = { - val a = new IntAccumulator - while (stepper.hasStep) a += stepper.nextStep - a - } - } - - implicit val accumulateLongStepper = new AccumulatesFromStepper[Long, LongAccumulator] { - def apply(stepper: Stepper[Long]) = { - val a = new LongAccumulator - while (stepper.hasStep) a += stepper.nextStep - a - } - } + implicit def richIntStepper(s: Stepper[Int]): StepperExtensions[Int] = new StepperExtensions[Int](s) + implicit def richLongStepper(s: Stepper[Long]): StepperExtensions[Long] = new StepperExtensions[Long](s) + implicit def richDoubleStepper(s: Stepper[Double]): StepperExtensions[Double] = new StepperExtensions[Double](s) } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala deleted file mode 100644 index 7358a1c..0000000 --- a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.collectionImpl - -import scala.language.higherKinds - -/** An `Accumulator` is a low-level collection specialized for gathering - * elements in parallel and then joining them in order by merging Accumulators. - * Accumulators can contain more than `Int.MaxValue` elements. - */ -final class Accumulator[A] extends AccumulatorLike[A, Accumulator[A]] { self => - private[java8] var current: Array[AnyRef] = Accumulator.emptyAnyRefArray - private[java8] var history: Array[Array[AnyRef]] = Accumulator.emptyAnyRefArrayArray - private[java8] var cumul: Array[Long] = Accumulator.emptyLongArray - - private[java8] def cumulative(i: Int) = cumul(i) - - private def expand(): Unit = { - if (index > 0) { - if (hIndex >= history.length) hExpand() - history(hIndex) = current - cumul(hIndex) = (if (hIndex > 0) cumulative(hIndex-1) else 0) + index - hIndex += 1 - } - current = new Array[AnyRef](nextBlockSize) - index = 0 - } - - private def hExpand(): Unit = { - if (hIndex == 0) { - history = new Array[Array[AnyRef]](4) - cumul = new Array[Long](4) - } - else { - history = java.util.Arrays.copyOf(history, history.length << 1) - cumul = java.util.Arrays.copyOf(cumul, cumul.length << 1) - } - } - - /** Appends an element to this `Accumulator`. */ - final def +=(a: A): Unit = { - totalSize += 1 - if (index >= current.length) expand() - current(index) = a.asInstanceOf[AnyRef] - index += 1 - } - - /** Removes all elements from `that` and appends them to this `Accumulator`. */ - final def drain[A1 <: A](that: Accumulator[A1]): Unit = { - var h = 0 - var prev = 0L - var more = true - while (more && h < that.hIndex) { - val n = (that.cumulative(h) - prev).toInt - if (current.length - index >= n) { - System.arraycopy(that.history(h), 0, current, index, n) - prev = that.cumulative(h) - index += n - h += 1 - } - else more = false - } - if (h >= that.hIndex && current.length - index >= that.index) { - if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) - index += that.index - } - else { - val slots = (if (index > 0) 1 else 0) + that.hIndex - h - if (hIndex + slots > history.length) { - val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) - history = java.util.Arrays.copyOf(history, n) - cumul = java.util.Arrays.copyOf(cumul, n) - } - var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) - if (index > 0) { - pv += index - cumul(hIndex) = pv - history(hIndex) = (if (index < (current.length >>> 3) && current.length > 32) java.util.Arrays.copyOf(current, index) else current) - hIndex += 1 - } - while (h < that.hIndex) { - pv += that.cumulative(h) - prev - prev = that.cumulative(h) - cumul(hIndex) = pv - history(hIndex) = that.history(h) - h += 1 - hIndex += 1 - } - index = that.index - current = that.current - } - totalSize += that.totalSize - that.clear - } - - override def clear(): Unit = { - super.clear() - current = Accumulator.emptyAnyRefArray - history = Accumulator.emptyAnyRefArrayArray - cumul = Accumulator.emptyLongArray - } - - /** Retrieves the `ix`th element. */ - final def apply(ix: Long): A = { - if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt).asInstanceOf[A] - else { - val w = seekSlot(ix) - history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt).asInstanceOf[A] - } - } - - /** Retrieves the `ix`th element, using an `Int` index. */ - final def apply(i: Int): A = apply(i.toLong) - - /** Returns a `Stepper` over the contents of this `Accumulator`*/ - final def stepper: AnyStepper[A] = new AccumulatorStepper[A](this) - - /** Returns an `Iterator` over the contents of this `Accumulator`. */ - final def iterator = stepper.iterator - - /** Returns a `java.util.Spliterator` over the contents of this `Accumulator`*/ - final def spliterator: java.util.Spliterator[A] = stepper.spliterator - - /** Produces a sequential Java 8 Stream over the elements of this `Accumulator`*/ - final def seqStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(spliterator, false) - - /** Produces a parallel Java 8 Stream over the elements of this `Accumulator`*/ - final def parStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(spliterator, true) - - /** Copies the elements in this `Accumulator` into an `Array` */ - final def toArray(implicit tag: reflect.ClassTag[A]) = { - if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) - val a = new Array[A](totalSize.toInt) - var j = 0 - var h = 0 - var pv = 0L - while (h < hIndex) { - val x = history(h) - val n = cumulative(h) - pv - pv = cumulative(h) - var i = 0 - while (i < n) { - a(j) = x(i).asInstanceOf[A] - i += 1 - j += 1 - } - h += 1 - } - var i = 0 - while (i < index) { - a(j) = current(i).asInstanceOf[A] - i += 1 - j += 1 - } - a - } - - /** Copies the elements in this `Accumulator` to a `List` */ - final def toList: List[A] = { - var ans: List[A] = Nil - var i = index - 1 - while (i >= 0) { - ans = current(i).asInstanceOf[A] :: ans - i -= 1 - } - var h = hIndex - 1 - while (h >= 0) { - val a = history(h) - i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 - while (i >= 0) { - ans = a(i).asInstanceOf[A] :: ans - i -= 1 - } - h -= 1 - } - ans - } - - /** Copies the elements in this `Accumulator` to a specified collection. - * Usage example: `acc.to[Vector]` - */ - final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, A, Coll[A]]): Coll[A] = { - if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) - val b = cbf() - b.sizeHint(totalSize.toInt) - var h = 0 - var pv = 0L - while (h < hIndex) { - val x = history(h) - val n = cumulative(h) - pv - pv = cumulative(h) - var i = 0 - while (i < n) { - b += x(i).asInstanceOf[A] - i += 1 - } - h += 1 - } - var i = 0 - while (i < index) { - b += current(i).asInstanceOf[A] - i += 1 - } - b.result - } -} - -object Accumulator { - private val emptyAnyRefArray = new Array[AnyRef](0) - private val emptyAnyRefArrayArray = new Array[Array[AnyRef]](0) - private val emptyLongArray = new Array[Long](0) - - /** A `Supplier` of `Accumulator`s, suitable for use with `java.util.stream.Stream`'s `collect` method. */ - def supplier[A] = new java.util.function.Supplier[Accumulator[A]]{ def get: Accumulator[A] = new Accumulator[A] } - - /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ - def adder[A] = new java.util.function.BiConsumer[Accumulator[A], A]{ def accept(ac: Accumulator[A], a: A): Unit = { ac += a } } - - /** A `BiConsumer` that merges `Accumulator`s, suitable for use with `java.util.stream.Stream`'s `collect` method. */ - def merger[A] = new java.util.function.BiConsumer[Accumulator[A], Accumulator[A]]{ def accept(a1: Accumulator[A], a2: Accumulator[A]): Unit = { a1 drain a2 } } - - /** Builds an `Accumulator` from any `TraversableOnce` */ - def from[A](source: TraversableOnce[A]) = { - val a = new Accumulator[A] - source.foreach(a += _) - a - } -} - -private[java8] class AccumulatorStepper[A](private val acc: Accumulator[A]) extends AnyStepper[A] { - import java.util.Spliterator._ - - private var h = 0 - private var i = 0 - private var a = if (acc.hIndex > 0) acc.history(0) else acc.current - private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index - private var N = acc.totalSize - - private def duplicateSelf(limit: Long): AccumulatorStepper[A] = { - val ans = new AccumulatorStepper(acc) - ans.h = h - ans.i = i - ans.a = a - ans.n = n - ans.N = limit - ans - } - - private def loadMore(): Unit = { - h += 1 - if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } - else { a = acc.current; n = acc.index } - i = 0 - } - - def characteristics() = ORDERED | SIZED | SUBSIZED - - def estimateSize = N - - def hasNext = N > 0 - - def next: A = - if (N <= 0) throw new NoSuchElementException("Next in empty Stepper") - else { - if (i >= n) loadMore() - val ans = a(i).asInstanceOf[A] - i += 1 - N -= 1 - ans - } - - // Overidden for efficiency - override def tryStep(f: A => Unit): Boolean = - if (N <= 0) false - else { - if (i >= n) loadMore() - f(a(i).asInstanceOf[A]) - i += 1 - N -= 1 - true - } - - // Overidden for efficiency - override def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = - if (N <= 0) false - else { - if (i >= n) loadMore() - f.accept(a(i).asInstanceOf[A]) - i += 1 - N -= 1 - true - } - - // Overridden for efficiency - override def foreach(f: A => Unit): Unit = { - while (N > 0) { - if (i >= n) loadMore() - val i0 = i - if ((n-i) > N) n = i + N.toInt - while (i < n) { - f(a(i).asInstanceOf[A]) - i += 1 - } - N -= (n - i0) - } - } - - // Overridden for efficiency - override def forEachRemaining(f: java.util.function.Consumer[_ >: A]): Unit = { - while (N > 0) { - if (i >= n) loadMore() - val i0 = i - if ((n-i) > N) n = i + N.toInt - while (i < n) { - f.accept(a(i).asInstanceOf[A]) - i += 1 - } - N -= (n - i0) - } - } - - def substep(): AnyStepper[A] = - if (N <= 1) null - else { - val half = (N >> 1) - val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i - val R = M + half - val ans = duplicateSelf(half) - if (h < acc.hIndex) { - val w = acc.seekSlot(R) - h = (w >>> 32).toInt - if (h < acc.hIndex) { - a = acc.history(h) - n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) - } - else { - a = acc.current - n = acc.index - } - i = (w & 0xFFFFFFFFL).toInt - } - else i += half.toInt - N -= half - ans - } - - override def toString = s"$h $i ${a.mkString("{",",","}")} $n $N" -} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala deleted file mode 100644 index 56519d2..0000000 --- a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.collectionImpl - -/** An accumulator that works with Java 8 streams; it accepts elements of type `A`, - * is itself an `AC`. Accumulators can handle more than `Int.MaxValue` elements. - */ -trait AccumulatorLike[@specialized(Double, Int, Long) A, AC] { - private[java8] var index: Int = 0 - private[java8] var hIndex: Int = 0 - private[java8] var totalSize: Long = 0L - private[java8] def cumulative(i: Int): Long - - private[java8] def nextBlockSize: Int = { - if (totalSize < 32) 16 - else if (totalSize <= Int.MaxValue) { - val bit = (64 - java.lang.Long.numberOfLeadingZeros(totalSize)) - 1 << (bit - (bit >> 2)) - } - else 1 << 24 - } - - /** Size of the accumulated collection, as a `Long` */ - final def size = totalSize - - /** Remove all accumulated elements from this accumulator. */ - def clear(): Unit = { - index = 0 - hIndex = 0 - totalSize = 0L - } - - private[java8] def seekSlot(ix: Long): Long = { - var lo = -1 - var hi = hIndex - while (lo + 1 < hi) { - val m = (lo + hi) >>> 1 // Shift allows division-as-unsigned, prevents overflow - if (cumulative(m) > ix) hi = m - else lo = m - } - (hi.toLong << 32) | (if (hi==0) ix else (ix - cumulative(hi-1))).toInt - } -} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala deleted file mode 100644 index b082769..0000000 --- a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.collectionImpl - -import scala.language.higherKinds - -/** A `DoubleAccumulator` is a low-level collection specialized for gathering - * elements in parallel and then joining them in order by merging them. - * This is a manually specialized variant of `Accumulator` with no actual - * subclassing relationship with `Accumulator`. - */ -final class DoubleAccumulator extends AccumulatorLike[Double, DoubleAccumulator] { self => - private[java8] var current: Array[Double] = DoubleAccumulator.emptyDoubleArray - private[java8] var history: Array[Array[Double]] = DoubleAccumulator.emptyDoubleArrayArray - - private[java8] def cumulative(i: Int) = { val x = history(i); x(x.length-1).toLong } - - private def expand(): Unit = { - if (index > 0) { - current(current.length-1) = (if (hIndex > 0) { val x = history(hIndex-1); x(x.length-1) } else 0) + index - if (hIndex >= history.length) hExpand() - history(hIndex) = current - hIndex += 1 - } - current = new Array[Double](nextBlockSize+1) - index = 0 - } - - private def hExpand(): Unit = { - if (hIndex == 0) history = new Array[Array[Double]](4) - else history = java.util.Arrays.copyOf(history, history.length << 1) - } - - /** Appends an element to this `DoubleAccumulator`. */ - final def +=(a: Double): Unit = { - totalSize += 1 - if (index+1 >= current.length) expand() - current(index) = a - index += 1 - } - - /** Removes all elements from `that` and appends them to this `DoubleAccumulator`. */ - final def drain(that: DoubleAccumulator): Unit = { - var h = 0 - var prev = 0L - var more = true - while (more && h < that.hIndex) { - val cuml = that.cumulative(h) - val n = (cuml - prev).toInt - if (current.length - index - 1 >= n) { - System.arraycopy(that.history(h), 0, current, index, n) - prev = cuml - index += n - h += 1 - } - else more = false - } - if (h >= that.hIndex && current.length - index - 1>= that.index) { - if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) - index += that.index - } - else { - val slots = (if (index > 0) 1 else 0) + that.hIndex - h - if (hIndex + slots > history.length) { - val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) - history = java.util.Arrays.copyOf(history, n) - } - var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) - if (index > 0) { - val x = - if (index < (current.length >>> 3) && current.length - 1 > 32) { - val ans = java.util.Arrays.copyOf(current, index + 1) - ans(ans.length - 1) = current(current.length - 1) - ans - } - else current - pv = pv + index - x(x.length - 1) = pv - history(hIndex) = x - hIndex += 1 - } - while (h < that.hIndex) { - val cuml = that.cumulative(h) - pv = pv + cuml - prev - prev = cuml - val x = that.history(h) - x(x.length - 1) = pv - history(hIndex) = x - h += 1 - hIndex += 1 - } - index = that.index - current = that.current - } - totalSize += that.totalSize - that.clear - } - - override def clear(): Unit = { - super.clear() - current = DoubleAccumulator.emptyDoubleArray - history = DoubleAccumulator.emptyDoubleArrayArray - } - - /** Retrieves the `ix`th element. */ - final def apply(ix: Long): Double = { - if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt) - else { - val w = seekSlot(ix) - history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt) - } - } - - /** Retrieves the `ix`th element, using an `Int` index. */ - final def apply(i: Int): Double = apply(i.toLong) - - /** Returns a `DoubleStepper` over the contents of this `DoubleAccumulator`. */ - final def stepper: DoubleStepper = new DoubleAccumulatorStepper(this) - - /** Returns an `Iterator` over the contents of this `DoubleAccumulator`. The `Iterator` is not specialized. */ - final def iterator = stepper.iterator - - /** Returns a `java.util.Spliterator.OfDouble` over the contents of this `DoubleAccumulator`*/ - final def spliterator: java.util.Spliterator.OfDouble = stepper - - /** Produces a sequential Java 8 `DoubleStream` over the elements of this `DoubleAccumulator`*/ - final def seqStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(spliterator, false) - - /** Produces a parallel Java 8 `DoubleStream` over the elements of this `DoubleAccumulator`*/ - final def parStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(spliterator, true) - - /** Copies the elements in this `DoubleAccumulator` into an `Array[Double]` */ - final def toArray = { - if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) - val a = new Array[Double](totalSize.toInt) - var j = 0 - var h = 0 - var pv = 0L - while (h < hIndex) { - val x = history(h) - val cuml = x(x.length-1).toLong - val n = (cuml - pv).toInt - pv = cuml - System.arraycopy(x, 0, a, j, n) - j += n - h += 1 - } - System.arraycopy(current, 0, a, j, index) - j += index - a - } - - /** Copies the elements in this `DoubleAccumulator` to a `List` */ - final def toList: List[Double] = { - var ans: List[Double] = Nil - var i = index - 1 - while (i >= 0) { - ans = current(i) :: ans - i -= 1 - } - var h = hIndex - 1 - while (h >= 0) { - val a = history(h) - i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 - while (i >= 0) { - ans = a(i) :: ans - i -= 1 - } - h -= 1 - } - ans - } - - /** Copies the elements in this `DoubleAccumulator` to a specified collection. - * Note that the target collection is not specialized. - * Usage example: `acc.to[Vector]` - */ - final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Double, Coll[Double]]): Coll[Double] = { - if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) - val b = cbf() - b.sizeHint(totalSize.toInt) - var h = 0 - var pv = 0L - while (h < hIndex) { - val x = history(h) - val n = cumulative(h) - pv - pv = cumulative(h) - var i = 0 - while (i < n) { - b += x(i) - i += 1 - } - h += 1 - } - var i = 0 - while (i < index) { - b += current(i) - i += 1 - } - b.result - } -} -object DoubleAccumulator { - private val emptyDoubleArray = new Array[Double](0) - private val emptyDoubleArrayArray = new Array[Array[Double]](0) - - /** A `Supplier` of `DoubleAccumulator`s, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. Suitable for `Stream[Double]` also. */ - def supplier = new java.util.function.Supplier[DoubleAccumulator]{ def get: DoubleAccumulator = new DoubleAccumulator } - - /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. */ - def adder = new java.util.function.ObjDoubleConsumer[DoubleAccumulator]{ def accept(ac: DoubleAccumulator, a: Double): Unit = { ac += a } } - - /** A `BiConsumer` that adds a boxed `Double` to an `DoubleAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ - def boxedAdder = new java.util.function.BiConsumer[DoubleAccumulator, Double]{ def accept(ac: DoubleAccumulator, a: Double): Unit = { ac += a } } - - /** A `BiConsumer` that merges `DoubleAccumulator`s, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. Suitable for `Stream[Double]` also. */ - def merger = new java.util.function.BiConsumer[DoubleAccumulator, DoubleAccumulator]{ def accept(a1: DoubleAccumulator, a2: DoubleAccumulator): Unit = { a1 drain a2 } } - - /** Builds a `DoubleAccumulator` from any `Double`-valued `TraversableOnce` */ - def from[A](source: TraversableOnce[Double]) = { - val a = new DoubleAccumulator - source.foreach(a += _) - a - } -} - -private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator) extends DoubleStepper { - import java.util.Spliterator._ - - private var h = 0 - private var i = 0 - private var a = if (acc.hIndex > 0) acc.history(0) else acc.current - private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index - private var N = acc.totalSize - - private def duplicateSelf(limit: Long): DoubleAccumulatorStepper = { - val ans = new DoubleAccumulatorStepper(acc) - ans.h = h - ans.i = i - ans.a = a - ans.n = n - ans.N = limit - ans - } - - private def loadMore(): Unit = { - h += 1 - if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } - else { a = acc.current; n = acc.index } - i = 0 - } - - def characteristics() = ORDERED | SIZED | SUBSIZED | NONNULL - - def estimateSize = N - - def hasNext = N > 0 - - def nextDouble: Double = - if (n <= 0) throw new NoSuchElementException("next on empty Stepper") - else { - if (i >= n) loadMore() - val ans = a(i) - i += 1 - N -= 1 - ans - } - - // Overridden for efficiency - override def tryStep(f: Double => Unit): Boolean = - if (N <= 0) false - else { - if (i >= n) loadMore() - f(a(i)) - i += 1 - N -= 1 - true - } - - // Overridden for efficiency - override def tryAdvance(f: java.util.function.DoubleConsumer): Boolean = - if (N <= 0) false - else { - if (i >= n) loadMore() - f.accept(a(i)) - i += 1 - N -= 1 - true - } - - // Overridden for efficiency - override def foreach(f: Double => Unit): Unit = { - while (N > 0) { - if (i >= n) loadMore() - val i0 = i - if ((n-i) > N) n = i + N.toInt - while (i < n) { - f(a(i)) - i += 1 - } - N -= (n - i0) - } - } - - // Overridden for efficiency - override def forEachRemaining(f: java.util.function.DoubleConsumer): Unit = { - while (N > 0) { - if (i >= n) loadMore() - val i0 = i - if ((n-i) > N) n = i + N.toInt - while (i < n) { - f.accept(a(i)) - i += 1 - } - N -= (n - i0) - } - } - - def substep(): DoubleStepper = - if (N <= 1) null - else { - val half = (N >> 1) - val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i - val R = M + half - val ans = duplicateSelf(half) - if (h < acc.hIndex) { - val w = acc.seekSlot(R) - h = (w >>> 32).toInt - if (h < acc.hIndex) { - a = acc.history(h) - n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) - } - else { - a = acc.current - n = acc.index - } - i = (w & 0xFFFFFFFFL).toInt - } - else i += half.toInt - N -= half - ans - } -} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala deleted file mode 100644 index 5054d26..0000000 --- a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.collectionImpl - -import scala.language.higherKinds - -/** A `IntAccumulator` is a low-level collection specialized for gathering - * elements in parallel and then joining them in order by merging them. - * This is a manually specialized variant of `Accumulator` with no actual - * subclassing relationship with `Accumulator`. - */ -final class IntAccumulator extends AccumulatorLike[Int, IntAccumulator] { self => - private[java8] var current: Array[Int] = IntAccumulator.emptyIntArray - private[java8] var history: Array[Array[Int]] = IntAccumulator.emptyIntArrayArray - - private[java8] def cumulative(i: Int) = { val x = history(i); x(x.length-2).toLong << 32 | (x(x.length-1)&0xFFFFFFFFL) } - - private def expand(): Unit = { - if (index > 0) { - val cuml = (if (hIndex > 0) cumulative(hIndex-1) else 0) + index - current(current.length-2) = (cuml >>> 32).toInt - current(current.length-1) = (cuml & 0xFFFFFFFFL).toInt - if (hIndex >= history.length) hExpand() - history(hIndex) = current - hIndex += 1 - } - current = new Array[Int](nextBlockSize+1) - index = 0 - } - - private def hExpand(): Unit = { - if (hIndex == 0) history = new Array[Array[Int]](4) - else history = java.util.Arrays.copyOf(history, history.length << 1) - } - - /** Appends an element to this `IntAccumulator`. */ - final def +=(a: Int): Unit = { - totalSize += 1 - if (index+2 >= current.length) expand() - current(index) = a - index += 1 - } - - /** Removes all elements from `that` and appends them to this `IntAccumulator`. */ - final def drain(that: IntAccumulator): Unit = { - var h = 0 - var prev = 0L - var more = true - while (more && h < that.hIndex) { - val cuml = that.cumulative(h) - val n = (cuml - prev).toInt - if (current.length - index - 2 >= n) { - System.arraycopy(that.history(h), 0, current, index, n) - prev = cuml - index += n - h += 1 - } - else more = false - } - if (h >= that.hIndex && current.length - index - 2 >= that.index) { - if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) - index += that.index - } - else { - val slots = (if (index > 0) 1 else 0) + that.hIndex - h - if (hIndex + slots > history.length) { - val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) - history = java.util.Arrays.copyOf(history, n) - } - var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) - if (index > 0) { - val x = - if (index < (current.length >>> 3) && current.length - 1 > 32) { - val ans = java.util.Arrays.copyOf(current, index + 2) - ans(ans.length - 2) = current(current.length - 2) - ans(ans.length - 1) = current(current.length - 1) - ans - } - else current - pv = pv + index - x(x.length - 2) = (pv >>> 32).toInt - x(x.length - 1) = (pv & 0xFFFFFFFFL).toInt - history(hIndex) = x - hIndex += 1 - } - while (h < that.hIndex) { - val cuml = that.cumulative(h) - pv = pv + cuml - prev - prev = cuml - val x = that.history(h) - x(x.length - 2) = (pv >>> 32).toInt - x(x.length - 1) = (pv & 0xFFFFFFFFL).toInt - history(hIndex) = x - h += 1 - hIndex += 1 - } - index = that.index - current = that.current - } - totalSize += that.totalSize - that.clear - } - - override def clear(): Unit = { - super.clear() - current = IntAccumulator.emptyIntArray - history = IntAccumulator.emptyIntArrayArray - } - - /** Retrieves the `ix`th element. */ - final def apply(ix: Long): Int = { - if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt) - else { - val w = seekSlot(ix) - history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt) - } - } - - /** Retrieves the `ix`th element, using an `Int` index. */ - final def apply(i: Int): Int = apply(i.toLong) - - /** Returns an `IntStepper` over the contents of this `IntAccumulator` */ - final def stepper: IntStepper = new IntAccumulatorStepper(this) - - /** Returns an `Iterator` over the contents of this `IntAccumulator`. The `Iterator` is not specialized. */ - final def iterator = stepper.iterator - - /** Returns a `java.util.Spliterator.OfInt` over the contents of this `IntAccumulator`*/ - final def spliterator: java.util.Spliterator.OfInt = stepper - - /** Produces a sequential Java 8 `IntStream` over the elements of this `IntAccumulator`*/ - final def seqStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(spliterator, false) - - /** Produces a parallel Java 8 `IntStream` over the elements of this `IntAccumulator`*/ - final def parStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(spliterator, true) - - /** Copies the elements in this `IntAccumulator` into an `Array[Int]` */ - final def toArray = { - if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) - val a = new Array[Int](totalSize.toInt) - var j = 0 - var h = 0 - var pv = 0L - while (h < hIndex) { - val x = history(h) - val cuml = cumulative(h) - val n = (cuml - pv).toInt - pv = cuml - System.arraycopy(x, 0, a, j, n) - j += n - h += 1 - } - System.arraycopy(current, 0, a, j, index) - j += index - a - } - - /** Copies the elements in this `IntAccumulator` to a `List` */ - final def toList: List[Int] = { - var ans: List[Int] = Nil - var i = index - 1 - while (i >= 0) { - ans = current(i) :: ans - i -= 1 - } - var h = hIndex - 1 - while (h >= 0) { - val a = history(h) - i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 - while (i >= 0) { - ans = a(i) :: ans - i -= 1 - } - h -= 1 - } - ans - } - - /** Copies the elements in this `IntAccumulator` to a specified collection. - * Note that the target collection is not specialized. - * Usage example: `acc.to[Vector]` - */ - final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, Coll[Int]]): Coll[Int] = { - if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) - val b = cbf() - b.sizeHint(totalSize.toInt) - var h = 0 - var pv = 0L - while (h < hIndex) { - val x = history(h) - val cuml = cumulative(h) - val n = cuml - pv - pv = cuml - var i = 0 - while (i < n) { - b += x(i) - i += 1 - } - h += 1 - } - var i = 0 - while (i < index) { - b += current(i) - i += 1 - } - b.result - } -} - -object IntAccumulator { - private val emptyIntArray = new Array[Int](0) - private val emptyIntArrayArray = new Array[Array[Int]](0) - - /** A `Supplier` of `IntAccumulator`s, suitable for use with `java.util.stream.IntStream`'s `collect` method. Suitable for `Stream[Int]` also. */ - def supplier = new java.util.function.Supplier[IntAccumulator]{ def get: IntAccumulator = new IntAccumulator } - - /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.IntStream`'s `collect` method. */ - def adder = new java.util.function.ObjIntConsumer[IntAccumulator]{ def accept(ac: IntAccumulator, a: Int): Unit = { ac += a } } - - /** A `BiConsumer` that adds a boxed `Int` to an `IntAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ - def boxedAdder = new java.util.function.BiConsumer[IntAccumulator, Int]{ def accept(ac: IntAccumulator, a: Int): Unit = { ac += a } } - - /** A `BiConsumer` that merges `IntAccumulator`s, suitable for use with `java.util.stream.IntStream`'s `collect` method. Suitable for `Stream[Int]` also. */ - def merger = new java.util.function.BiConsumer[IntAccumulator, IntAccumulator]{ def accept(a1: IntAccumulator, a2: IntAccumulator): Unit = { a1 drain a2 } } - - /** Builds an `IntAccumulator` from any `Int`-valued `TraversableOnce` */ - def from[A](source: TraversableOnce[Int]) = { - val a = new IntAccumulator - source.foreach(a += _) - a - } -} - -private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) extends IntStepper { - import java.util.Spliterator._ - - private var h = 0 - private var i = 0 - private var a = if (acc.hIndex > 0) acc.history(0) else acc.current - private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index - private var N = acc.totalSize - - private def duplicateSelf(limit: Long): IntAccumulatorStepper = { - val ans = new IntAccumulatorStepper(acc) - ans.h = h - ans.i = i - ans.a = a - ans.n = n - ans.N = limit - ans - } - - private def loadMore(): Unit = { - h += 1 - if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } - else { a = acc.current; n = acc.index } - i = 0 - } - - def characteristics() = ORDERED | SIZED | SUBSIZED | NONNULL - - def estimateSize = N - - def hasNext = N > 0 - - def nextInt: Int = - if (N <= 0) throw new NoSuchElementException("next on empty Stepper") - else { - if (i >= n) loadMore() - val ans = a(i) - i += 1 - N -= 1 - ans - } - - // Overridden for efficiency - override def tryStep(f: Int => Unit): Boolean = - if (N <= 0) false - else { - if (i >= n) loadMore() - f(a(i)) - i += 1 - N -= 1 - true - } - - // Overridden for efficiency - override def tryAdvance(f: java.util.function.IntConsumer): Boolean = - if (N <= 0) false - else { - if (i >= n) loadMore() - f.accept(a(i)) - i += 1 - N -= 1 - true - } - - // Overridden for efficiency - override def foreach(f: Int => Unit): Unit = { - while (N > 0) { - if (i >= n) loadMore() - val i0 = i - if ((n-i) > N) n = i + N.toInt - while (i < n) { - f(a(i)) - i += 1 - } - N -= (n - i0) - } - } - - // Overridden for efficiency - override def forEachRemaining(f: java.util.function.IntConsumer): Unit = { - while (N > 0) { - if (i >= n) loadMore() - val i0 = i - if ((n-i) > N) n = i + N.toInt - while (i < n) { - f.accept(a(i)) - i += 1 - } - N -= (n - i0) - } - } - - def substep(): IntStepper = - if (N <= 1) null - else { - val half = (N >> 1) - val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i - val R = M + half - val ans = duplicateSelf(half) - if (h < acc.hIndex) { - val w = acc.seekSlot(R) - h = (w >>> 32).toInt - if (h < acc.hIndex) { - a = acc.history(h) - n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) - } - else { - a = acc.current - n = acc.index - } - i = (w & 0xFFFFFFFFL).toInt - } - else i += half.toInt - N -= half - ans - } -} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala deleted file mode 100644 index b924a71..0000000 --- a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.collectionImpl - -import scala.language.higherKinds - -/** A `LongAccumulator` is a low-level collection specialized for gathering - * elements in parallel and then joining them in order by merging them. - * This is a manually specialized variant of `Accumulator` with no actual - * subclassing relationship with `Accumulator`. - */ -final class LongAccumulator extends AccumulatorLike[Long, LongAccumulator] { self => - private[java8] var current: Array[Long] = LongAccumulator.emptyLongArray - private[java8] var history: Array[Array[Long]] = LongAccumulator.emptyLongArrayArray - - private[java8] def cumulative(i: Int) = { val x = history(i); x(x.length-1) } - - private def expand(): Unit = { - if (index > 0) { - current(current.length-1) = (if (hIndex > 0) { val x = history(hIndex-1); x(x.length-1) } else 0) + index - if (hIndex >= history.length) hExpand() - history(hIndex) = current - hIndex += 1 - } - current = new Array[Long](nextBlockSize+1) - index = 0 - } - - private def hExpand(): Unit = { - if (hIndex == 0) history = new Array[Array[Long]](4) - else history = java.util.Arrays.copyOf(history, history.length << 1) - } - - /** Appends an element to this `LongAccumulator`. */ - final def +=(a: Long): Unit = { - totalSize += 1 - if (index+1 >= current.length) expand() - current(index) = a - index += 1 - } - - /** Removes all elements from `that` and appends them to this `LongAccumulator`. */ - final def drain(that: LongAccumulator): Unit = { - var h = 0 - var prev = 0L - var more = true - while (more && h < that.hIndex) { - val cuml = that.cumulative(h) - val n = (cuml - prev).toInt - if (current.length - index - 1 >= n) { - System.arraycopy(that.history(h), 0, current, index, n) - prev = cuml - index += n - h += 1 - } - else more = false - } - if (h >= that.hIndex && current.length - index - 1>= that.index) { - if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) - index += that.index - } - else { - val slots = (if (index > 0) 1 else 0) + that.hIndex - h - if (hIndex + slots > history.length) { - val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) - history = java.util.Arrays.copyOf(history, n) - } - var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) - if (index > 0) { - val x = - if (index < (current.length >>> 3) && current.length - 1 > 32) { - val ans = java.util.Arrays.copyOf(current, index + 1) - ans(ans.length - 1) = current(current.length - 1) - ans - } - else current - pv = pv + index - x(x.length - 1) = pv - history(hIndex) = x - hIndex += 1 - } - while (h < that.hIndex) { - val cuml = that.cumulative(h) - pv = pv + cuml - prev - prev = cuml - val x = that.history(h) - x(x.length - 1) = pv - history(hIndex) = x - h += 1 - hIndex += 1 - } - index = that.index - current = that.current - } - totalSize += that.totalSize - that.clear - } - - override def clear(): Unit = { - super.clear() - current = LongAccumulator.emptyLongArray - history = LongAccumulator.emptyLongArrayArray - } - - /** Retrieves the `ix`th element. */ - final def apply(ix: Long): Long = { - if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt) - else { - val w = seekSlot(ix) - history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt) - } - } - - /** Retrieves the `ix`th element, using an `Int` index. */ - final def apply(i: Int): Long = apply(i.toLong) - - /** Returns a `LongStepper` over the contents of this `LongAccumulator`. */ - final def stepper: LongStepper = new LongAccumulatorStepper(this) - - /** Returns an `Iterator` over the contents of this `LongAccumulator`. The `Iterator` is not specialized. */ - final def iterator = stepper.iterator - - /** Returns a `java.util.Spliterator.OfLong` over the contents of this `LongAccumulator`*/ - final def spliterator: java.util.Spliterator.OfLong = stepper - - /** Produces a sequential Java 8 `LongStream` over the elements of this `LongAccumulator`*/ - final def seqStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(spliterator, false) - - /** Produces a parallel Java 8 `LongStream` over the elements of this `LongAccumulator`*/ - final def parStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(spliterator, true) - - /** Copies the elements in this `LongAccumulator` into an `Array[Long]` */ - final def toArray = { - if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) - val a = new Array[Long](totalSize.toInt) - var j = 0 - var h = 0 - var pv = 0L - while (h < hIndex) { - val x = history(h) - val cuml = x(x.length-1) - val n = (cuml - pv).toInt - pv = cuml - System.arraycopy(x, 0, a, j, n) - j += n - h += 1 - } - System.arraycopy(current, 0, a, j, index) - j += index - a - } - - /** Copies the elements in this `LongAccumulator` to a `List` */ - final def toList: List[Long] = { - var ans: List[Long] = Nil - var i = index - 1 - while (i >= 0) { - ans = current(i) :: ans - i -= 1 - } - var h = hIndex - 1 - while (h >= 0) { - val a = history(h) - i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 - while (i >= 0) { - ans = a(i) :: ans - i -= 1 - } - h -= 1 - } - ans - } - - /** Copies the elements in this `LongAccumulator` to a specified collection. - * Note that the target collection is not specialized. - * Usage example: `acc.to[Vector]` - */ - final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Long, Coll[Long]]): Coll[Long] = { - if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) - val b = cbf() - b.sizeHint(totalSize.toInt) - var h = 0 - var pv = 0L - while (h < hIndex) { - val x = history(h) - val n = cumulative(h) - pv - pv = cumulative(h) - var i = 0 - while (i < n) { - b += x(i) - i += 1 - } - h += 1 - } - var i = 0 - while (i < index) { - b += current(i) - i += 1 - } - b.result - } -} - -object LongAccumulator { - private val emptyLongArray = new Array[Long](0) - private val emptyLongArrayArray = new Array[Array[Long]](0) - - /** A `Supplier` of `LongAccumulator`s, suitable for use with `java.util.stream.LongStream`'s `collect` method. Suitable for `Stream[Long]` also. */ - def supplier = new java.util.function.Supplier[LongAccumulator]{ def get: LongAccumulator = new LongAccumulator } - - /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.LongStream`'s `collect` method. */ - def adder = new java.util.function.ObjLongConsumer[LongAccumulator]{ def accept(ac: LongAccumulator, a: Long): Unit = { ac += a } } - - /** A `BiConsumer` that adds a boxed `Long` to an `LongAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ - def boxedAdder = new java.util.function.BiConsumer[LongAccumulator, Long]{ def accept(ac: LongAccumulator, a: Long): Unit = { ac += a } } - - /** A `BiConsumer` that merges `LongAccumulator`s, suitable for use with `java.util.stream.LongStream`'s `collect` method. Suitable for `Stream[Long]` also. */ - def merger = new java.util.function.BiConsumer[LongAccumulator, LongAccumulator]{ def accept(a1: LongAccumulator, a2: LongAccumulator): Unit = { a1 drain a2 } } - - /** Builds a `LongAccumulator` from any `Long`-valued `TraversableOnce` */ - def from[A](source: TraversableOnce[Long]) = { - val a = new LongAccumulator - source.foreach(a += _) - a - } -} - -private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) extends LongStepper { - import java.util.Spliterator._ - - private var h = 0 - private var i = 0 - private var a = if (acc.hIndex > 0) acc.history(0) else acc.current - private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index - private var N = acc.totalSize - - private def duplicateSelf(limit: Long): LongAccumulatorStepper = { - val ans = new LongAccumulatorStepper(acc) - ans.h = h - ans.i = i - ans.a = a - ans.n = n - ans.N = limit - ans - } - - private def loadMore(): Unit = { - h += 1 - if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } - else { a = acc.current; n = acc.index } - i = 0 - } - - def characteristics() = ORDERED | SIZED | SUBSIZED | NONNULL - - def estimateSize = N - - def hasNext = N > 0 - - def nextLong: Long = - if (n <= 0) throw new NoSuchElementException("next on empty Stepper") - else { - if (i >= n) loadMore() - val ans = a(i) - i += 1 - N -= 1 - ans - } - - // Overridden for efficiency - override def tryStep(f: Long => Unit): Boolean = - if (N <= 0) false - else { - if (i >= n) loadMore() - f(a(i)) - i += 1 - N -= 1 - true - } - - // Overridden for efficiency - override def tryAdvance(f: java.util.function.LongConsumer): Boolean = - if (N <= 0) false - else { - if (i >= n) loadMore() - f.accept(a(i)) - i += 1 - N -= 1 - true - } - - // Overridden for efficiency - override def foreach(f: Long => Unit): Unit = { - while (N > 0) { - if (i >= n) loadMore() - val i0 = i - if ((n-i) > N) n = i + N.toInt - while (i < n) { - f(a(i)) - i += 1 - } - N -= (n - i0) - } - } - - // Overridden for efficiency - override def forEachRemaining(f: java.util.function.LongConsumer): Unit = { - while (N > 0) { - if (i >= n) loadMore() - val i0 = i - if ((n-i) > N) n = i + N.toInt - while (i < n) { - f.accept(a(i)) - i += 1 - } - N -= (n - i0) - } - } - - def substep(): LongStepper = - if (N <= 1) null - else { - val half = (N >> 1) - val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i - val R = M + half - val ans = duplicateSelf(half) - if (h < acc.hIndex) { - val w = acc.seekSlot(R) - h = (w >>> 32).toInt - if (h < acc.hIndex) { - a = acc.history(h) - n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) - } - else { - a = acc.current - n = acc.index - } - i = (w & 0xFFFFFFFFL).toInt - } - else i += half.toInt - N -= half - ans - } -} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala deleted file mode 100644 index 8e13ea1..0000000 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ /dev/null @@ -1,641 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.collectionImpl - -import scala.language.higherKinds - -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): 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): Unit = { if (myCacheIsFull) { f(myCache); myCacheIsFull = false }; foreachUncached(f) } - protected def foreachUncached(f: A => Unit): 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]): Unit = { 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]] { - override def forEachRemaining(c: java.util.function.Consumer[_ >: A]): Unit = { 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] { - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]): Unit = { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } - override def forEachRemaining(c: java.util.function.DoubleConsumer): Unit = { while (hasNext) { c.accept(nextDouble) } } - def hasStep = hasNext() - def knownSize = getExactSizeIfKnown - def nextStep = nextDouble - override 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] { - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]): Unit = { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } - override def forEachRemaining(c: java.util.function.IntConsumer): Unit = { while (hasNext) { c.accept(nextInt) } } - def hasStep = hasNext() - def knownSize = getExactSizeIfKnown - def nextStep = nextInt - override 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] { - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]): Unit = { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } - override def forEachRemaining(c: java.util.function.LongConsumer): Unit = { while (hasNext) { c.accept(nextLong) } } - def hasStep = hasNext() - def knownSize = getExactSizeIfKnown - def nextStep = nextLong - override 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): Unit = { 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]): Unit = { - 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): Unit = { 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): Unit = { - 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): Unit = { 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): Unit = { - 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): Unit = { 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): Unit = { - 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 anumeric type into a possibly 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 boxed. In other cases native implementations of the primitive stepper types should be provided - * (see for example StepsIntArray and StepsWidenedByteArray). */ - - private[java8] class UnboxingDoubleStepper(st: AnyStepper[Double]) extends DoubleStepper { - def hasNext(): Boolean = st.hasNext() - def nextDouble(): Double = st.next() - def characteristics(): Int = st.characteristics() - def estimateSize(): Long = st.estimateSize() - def substep(): DoubleStepper = new UnboxingDoubleStepper(st.substep()) - } - - private[java8] class UnboxingIntStepper(st: AnyStepper[Int]) extends IntStepper { - def hasNext(): Boolean = st.hasNext() - def nextInt(): Int = st.next() - def characteristics(): Int = st.characteristics() - def estimateSize(): Long = st.estimateSize() - def substep(): IntStepper = new UnboxingIntStepper(st.substep()) - } - - private[java8] class UnboxingLongStepper(st: AnyStepper[Long]) extends LongStepper { - def hasNext(): Boolean = st.hasNext() - def nextLong(): Long = st.next() - def characteristics(): Int = st.characteristics() - def estimateSize(): Long = st.estimateSize() - def substep(): LongStepper = new UnboxingLongStepper(st.substep()) - } - - private[java8] class UnboxingByteStepper(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 UnboxingByteStepper(st.substep()) - } - - private[java8] class UnboxingCharStepper(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 UnboxingCharStepper(st.substep()) - } - - private[java8] class UnboxingShortStepper(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 UnboxingShortStepper(st.substep()) - } - - private[java8] class UnboxingFloatStepper(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 UnboxingFloatStepper(st.substep()) - } -} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/package.scala b/src/main/scala/scala/compat/java8/collectionImpl/package.scala new file mode 100644 index 0000000..ab5cfca --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/package.scala @@ -0,0 +1,30 @@ +package scala.compat.java8 + +package object collectionImpl { + type Accumulator[A] = scala.jdk.AnyAccumulator[A] + val Accumulator = scala.jdk.AnyAccumulator + + type IntAccumulator = scala.jdk.IntAccumulator + val IntAccumulator = scala.jdk.IntAccumulator + + type LongAccumulator = scala.jdk.LongAccumulator + val LongAccumulator = scala.jdk.LongAccumulator + + type DoubleAccumulator = scala.jdk.DoubleAccumulator + val DoubleAccumulator = scala.jdk.DoubleAccumulator + + type Stepper[A] = scala.collection.Stepper[A] + val Stepper = scala.collection.Stepper + + type AnyStepper[A] = scala.collection.AnyStepper[A] + val AnyStepper = scala.collection.AnyStepper + + type IntStepper = scala.collection.IntStepper + val IntStepper = scala.collection.IntStepper + + type LongStepper = scala.collection.LongStepper + val LongStepper = scala.collection.LongStepper + + type DoubleStepper = scala.collection.DoubleStepper + val DoubleStepper = scala.collection.DoubleStepper +} diff --git a/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala b/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala index ff40e53..fa28114 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala @@ -14,74 +14,34 @@ package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ -trait AccumulatesFromStepper[@specialized(Double, Int, Long) A, Acc <: AccumulatorLike[A, Acc]] { - def apply(stepper: Stepper[A]): Acc +final class CollectionCanAccumulate[A](private val underlying: IterableOnce[A]) extends AnyVal { + def accumulate: Accumulator[A] = underlying.iterator.to(Accumulator) } -final class CollectionCanAccumulate[A](private val underlying: TraversableOnce[A]) extends AnyVal { - def accumulate: Accumulator[A] = { - val a = new Accumulator[A] - underlying.foreach(a += _) - a - } +final class AccumulateDoubleCollection(private val underlying: IterableOnce[Double]) extends AnyVal { + def accumulate: DoubleAccumulator = underlying.iterator.to(DoubleAccumulator) } -final class AccumulateDoubleCollection(private val underlying: TraversableOnce[Double]) extends AnyVal { - def accumulate: DoubleAccumulator = { - val da = new DoubleAccumulator - underlying.foreach(da += _) - da - } +final class AccumulateIntCollection(private val underlying: IterableOnce[Int]) extends AnyVal { + def accumulate: IntAccumulator = underlying.iterator.to(IntAccumulator) } -final class AccumulateIntCollection(private val underlying: TraversableOnce[Int]) extends AnyVal { - def accumulate: IntAccumulator = { - val da = new IntAccumulator - underlying.foreach(da += _) - da - } -} - -final class AccumulateLongCollection(private val underlying: TraversableOnce[Long]) extends AnyVal { - def accumulate: LongAccumulator = { - val da = new LongAccumulator - underlying.foreach(da += _) - da - } +final class AccumulateLongCollection(private val underlying: IterableOnce[Long]) extends AnyVal { + def accumulate: LongAccumulator = underlying.iterator.to(LongAccumulator) } final class AccumulateAnyArray[A](private val underlying: Array[A]) extends AnyVal { - def accumulate: Accumulator[A] = { - val a = new Accumulator[A] - var i = 0 - while (i < underlying.length) { a += underlying(i); i += 1 } - a - } + def accumulate: Accumulator[A] = underlying.to(Accumulator) } final class AccumulateDoubleArray(private val underlying: Array[Double]) extends AnyVal { - def accumulate: DoubleAccumulator = { - val da = new DoubleAccumulator - var i = 0 - while (i < underlying.length) { da += underlying(i); i += 1 } - da - } + def accumulate: DoubleAccumulator = underlying.to(DoubleAccumulator) } final class AccumulateIntArray(private val underlying: Array[Int]) extends AnyVal { - def accumulate: IntAccumulator = { - val da = new IntAccumulator - var i = 0 - while (i < underlying.length) { da += underlying(i); i += 1 } - da - } + def accumulate: IntAccumulator = underlying.to(IntAccumulator) } final class AccumulateLongArray(private val underlying: Array[Long]) extends AnyVal { - def accumulate: LongAccumulator = { - val da = new LongAccumulator - var i = 0 - while (i < underlying.length) { da += underlying(i); i += 1 } - da - } + def accumulate: LongAccumulator = underlying.to(LongAccumulator) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala b/src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala index 5b3e77f..4ff943a 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala @@ -12,18 +12,16 @@ package scala.compat.java8.converterImpl -import language.implicitConversions - -import scala.compat.java8.collectionImpl._ +import scala.language.implicitConversions trait Priority3AccumulatorConverters { - implicit def collectionCanAccumulate[A](underlying: TraversableOnce[A]) = new CollectionCanAccumulate[A](underlying) + implicit def collectionCanAccumulate[A](underlying: IterableOnce[A]) = new CollectionCanAccumulate[A](underlying) } trait Priority2AccumulatorConverters extends Priority3AccumulatorConverters { - implicit def accumulateDoubleCollection(underlying: TraversableOnce[Double]) = new AccumulateDoubleCollection(underlying) - implicit def accumulateIntCollection(underlying: TraversableOnce[Int]) = new AccumulateIntCollection(underlying) - implicit def accumulateLongCollection(underlying: TraversableOnce[Long]) = new AccumulateLongCollection(underlying) + implicit def accumulateDoubleCollection(underlying: IterableOnce[Double]) = new AccumulateDoubleCollection(underlying) + implicit def accumulateIntCollection(underlying: IterableOnce[Int]) = new AccumulateIntCollection(underlying) + implicit def accumulateLongCollection(underlying: IterableOnce[Long]) = new AccumulateLongCollection(underlying) implicit def accumulateAnyArray[A](underlying: Array[A]) = new AccumulateAnyArray(underlying) } @@ -31,17 +29,4 @@ trait Priority1AccumulatorConverters extends Priority2AccumulatorConverters { implicit def accumulateDoubleArray(underlying: Array[Double]) = new AccumulateDoubleArray(underlying) implicit def accumulateIntArray(underlying: Array[Int]) = new AccumulateIntArray(underlying) implicit def accumulateLongArray(underlying: Array[Long]) = new AccumulateLongArray(underlying) - - implicit def accumulateAnyStepper[A]: AccumulatesFromStepper[A, Accumulator[A]] = - PrivateAccumulatorConverters.genericAccumulateAnyStepper.asInstanceOf[AccumulatesFromStepper[A, Accumulator[A]]] -} - -private[java8] object PrivateAccumulatorConverters { - val genericAccumulateAnyStepper: AccumulatesFromStepper[Any, Accumulator[Any]] = new AccumulatesFromStepper[Any, Accumulator[Any]] { - def apply(stepper: Stepper[Any]) = { - val a = new Accumulator[Any] - while (stepper.hasStep) a += stepper.nextStep - a - } - } } diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala deleted file mode 100644 index e73e4d2..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.compat.java8.collectionImpl._ - -trait MakesStepper[T, +Extra] extends Any { - /** Generates a fresh stepper of type `S` for element type `T` */ - def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]): S with Extra -} - -trait MakesKeyValueStepper[K, V, +Extra] extends Any { - /** Generates a fresh stepper of type `S` over map keys of type `K` */ - def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]): S with Extra - - /** Generates a fresh stepper of type `S` over map values of type `V` */ - def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]): S with Extra -} - -/** Encodes the translation from an element type `T` to the corresponding Stepper type `S` */ -sealed trait StepperShape[T, S <: Stepper[_]] { - /** Return the Int constant (as defined in the `StepperShape` companion object) for this `StepperShape`. */ - def shape: Int - - /** Create an unboxing primitive sequential Stepper from a boxed `AnyStepper`. - * This is an identity operation for reference shapes. */ - def seqUnbox(st: AnyStepper[T]): S - - /** Create an unboxing primitive parallel (i.e. `with EfficientSubstep`) Stepper from a boxed `AnyStepper`. - * This is an identity operation for reference shapes. */ - def parUnbox(st: AnyStepper[T] with EfficientSubstep): S with EfficientSubstep -} -object StepperShape extends StepperShapeLowPriority { - // reference - final val Reference = 0 - - // primitive - final val IntValue = 1 - final val LongValue = 2 - final val DoubleValue = 3 - - // widening - final val ByteValue = 4 - final val ShortValue = 5 - final val CharValue = 6 - final val FloatValue = 7 - - implicit val intStepperShape: StepperShape[Int, IntStepper] = new StepperShape[Int, IntStepper] { - def shape = IntValue - def seqUnbox(st: AnyStepper[Int]): IntStepper = new Stepper.UnboxingIntStepper(st) - def parUnbox(st: AnyStepper[Int] with EfficientSubstep): IntStepper with EfficientSubstep = new Stepper.UnboxingIntStepper(st) with EfficientSubstep - } - implicit val longStepperShape: StepperShape[Long, LongStepper] = new StepperShape[Long, LongStepper] { - def shape = LongValue - def seqUnbox(st: AnyStepper[Long]): LongStepper = new Stepper.UnboxingLongStepper(st) - def parUnbox(st: AnyStepper[Long] with EfficientSubstep): LongStepper with EfficientSubstep = new Stepper.UnboxingLongStepper(st) with EfficientSubstep - } - implicit val doubleStepperShape: StepperShape[Double, DoubleStepper] = new StepperShape[Double, DoubleStepper] { - def shape = DoubleValue - def seqUnbox(st: AnyStepper[Double]): DoubleStepper = new Stepper.UnboxingDoubleStepper(st) - def parUnbox(st: AnyStepper[Double] with EfficientSubstep): DoubleStepper with EfficientSubstep = new Stepper.UnboxingDoubleStepper(st) with EfficientSubstep - } - implicit val byteStepperShape: StepperShape[Byte, IntStepper] = new StepperShape[Byte, IntStepper] { - def shape = ByteValue - def seqUnbox(st: AnyStepper[Byte]): IntStepper = new Stepper.UnboxingByteStepper(st) - def parUnbox(st: AnyStepper[Byte] with EfficientSubstep): IntStepper with EfficientSubstep = new Stepper.UnboxingByteStepper(st) with EfficientSubstep - } - implicit val shortStepperShape: StepperShape[Short, IntStepper] = new StepperShape[Short, IntStepper] { - def shape = ShortValue - def seqUnbox(st: AnyStepper[Short]): IntStepper = new Stepper.UnboxingShortStepper(st) - def parUnbox(st: AnyStepper[Short] with EfficientSubstep): IntStepper with EfficientSubstep = new Stepper.UnboxingShortStepper(st) with EfficientSubstep - } - implicit val charStepperShape: StepperShape[Char, IntStepper] = new StepperShape[Char, IntStepper] { - def shape = CharValue - def seqUnbox(st: AnyStepper[Char]): IntStepper = new Stepper.UnboxingCharStepper(st) - def parUnbox(st: AnyStepper[Char] with EfficientSubstep): IntStepper with EfficientSubstep = new Stepper.UnboxingCharStepper(st) with EfficientSubstep - } - implicit val floatStepperShape: StepperShape[Float, DoubleStepper] = new StepperShape[Float, DoubleStepper] { - def shape = FloatValue - def seqUnbox(st: AnyStepper[Float]): DoubleStepper = new Stepper.UnboxingFloatStepper(st) - def parUnbox(st: AnyStepper[Float] with EfficientSubstep): DoubleStepper with EfficientSubstep = new Stepper.UnboxingFloatStepper(st) with EfficientSubstep - } -} -trait StepperShapeLowPriority { - implicit def anyStepperShape[T] = anyStepperShapePrototype.asInstanceOf[StepperShape[T, AnyStepper[T]]] - - private[this] val anyStepperShapePrototype: StepperShape[AnyRef, AnyStepper[AnyRef]] = new StepperShape[AnyRef, AnyStepper[AnyRef]] { - def shape = StepperShape.Reference - def seqUnbox(st: AnyStepper[AnyRef]): AnyStepper[AnyRef] = st - def parUnbox(st: AnyStepper[AnyRef] with EfficientSubstep): AnyStepper[AnyRef] with EfficientSubstep = st - } -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala b/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala deleted file mode 100644 index e6752dc..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import language.implicitConversions - -trait Priority3StepConverters { - implicit def richIterableCanStep[A](underlying: Iterable[A]) = new RichIterableCanStep(underlying) - implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) -} - -trait Priority2StepConverters extends Priority3StepConverters { - implicit def richLinearSeqCanStep[A](underlying: collection.LinearSeq[A]) = new RichLinearSeqCanStep[A](underlying) - implicit def richIndexedSeqCanStep[A](underlying: collection.IndexedSeqLike[A, _]) = new RichIndexedSeqCanStep[A](underlying) -} - -trait Priority1StepConverters extends Priority2StepConverters { - implicit def richDefaultHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = new RichDefaultHashTableCanStep[K, V](underlying) - implicit def richLinkedHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = new RichLinkedHashTableCanStep[K, V](underlying) - implicit def richArrayCanStep[A](underlying: Array[A]) = new RichArrayCanStep[A](underlying) - implicit def richWrappedArrayCanStep[A](underlying: collection.mutable.WrappedArray[A]) = new RichArrayCanStep[A](underlying.array) - implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) - implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) - implicit def richImmHashMapCanStep[K, V](underlying: collection.immutable.HashMap[K, V]) = new RichImmHashMapCanStep[K, V](underlying) - implicit def richImmHashSetCanStep[A](underlying: collection.immutable.HashSet[A]) = new RichImmHashSetCanStep[A](underlying) - implicit def richNumericRangeCanStep[T](underlying: collection.immutable.NumericRange[T]) = new RichNumericRangeCanStep(underlying) - implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) - implicit def richBitSetCanStep(underlying: collection.BitSet) = new RichBitSetCanStep(underlying) - implicit def richRangeCanStep(underlying: Range) = new RichRangeCanStep(underlying) - implicit def richStringCanStep(underlying: String) = new RichStringCanStep(underlying) -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepperExtensions.scala b/src/main/scala/scala/compat/java8/converterImpl/StepperExtensions.scala new file mode 100644 index 0000000..15f384a --- /dev/null +++ b/src/main/scala/scala/compat/java8/converterImpl/StepperExtensions.scala @@ -0,0 +1,77 @@ +package scala.compat.java8.converterImpl + +import scala.collection.convert.StreamExtensions.AccumulatorFactoryInfo +import scala.compat.java8.collectionImpl.{DoubleAccumulator, IntAccumulator, LongAccumulator, Stepper} +import scala.jdk.AnyAccumulator + +class StepperExtensions[@specialized(Double, Int, Long) A](private val s: Stepper[A]) { + def accumulate[C](implicit info: AccumulatorFactoryInfo[A, C]): C = { + info.companion match { + case IntAccumulator => + val a = new IntAccumulator() + val is = s.asInstanceOf[Stepper[Int]] + while (is.hasStep) a += is.nextStep() + a.asInstanceOf[C] + case LongAccumulator => + val a = new LongAccumulator() + val is = s.asInstanceOf[Stepper[Long]] + while (is.hasStep) a += is.nextStep() + a.asInstanceOf[C] + case DoubleAccumulator => + val a = new DoubleAccumulator() + val is = s.asInstanceOf[Stepper[Double]] + while (is.hasStep) a += is.nextStep() + a.asInstanceOf[C] + case AnyAccumulator | null => + val a = new AnyAccumulator[A] + while (s.hasStep) a += s.nextStep() + a.asInstanceOf[C] + } + } + + def substep(): Stepper[A] = s.trySplit() + + /** Consumes all remaining elements in this `Stepper` and counts how many there are. + * This is a terminal operation. + */ + def count(): Long = { var n = 0L; while (s.hasStep) { s.nextStep(); n += 1 }; n } + + /** 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 (s.hasStep) { if (p(s.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(s.hasStep) { if (p(s.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 (s.hasStep) { val a = s.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 (s.hasStep) { b = op(b, s.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) && s.hasStep) { b = op(b, s.nextStep()) }; b } + + /** Applies `f` to every remaining element in the collection. + * This is a terminal operation. + */ + def foreach(f: A => Unit): Unit = { while (s.hasStep) f(s.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 = s.nextStep(); while (s.hasStep) { a = op(a, s.nextStep()) }; a } +} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala deleted file mode 100644 index d77daac..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.compat.java8.collectionImpl._ - -import Stepper._ - -///////////////////////////// -// Stepper implementations // -///////////////////////////// - -private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) -extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsObjectArray[A](underlying, i0, half) -} - -private[java8] class StepsBoxedBooleanArray(underlying: Array[Boolean], _i0: Int, _iN: Int) -extends StepsLikeIndexed[Boolean, StepsBoxedBooleanArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedBooleanArray(underlying, i0, half) -} - -private[java8] class StepsWidenedByteArray(underlying: Array[Byte], _i0: Int, _iN: Int) -extends StepsIntLikeIndexed[StepsWidenedByteArray](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsWidenedByteArray(underlying, i0, half) -} - -private[java8] class StepsWidenedCharArray(underlying: Array[Char], _i0: Int, _iN: Int) -extends StepsIntLikeIndexed[StepsWidenedCharArray](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsWidenedCharArray(underlying, i0, half) -} - -private[java8] class StepsWidenedShortArray(underlying: Array[Short], _i0: Int, _iN: Int) -extends StepsIntLikeIndexed[StepsWidenedShortArray](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsWidenedShortArray(underlying, i0, half) -} - -private[java8] class StepsWidenedFloatArray(underlying: Array[Float], _i0: Int, _iN: Int) -extends StepsDoubleLikeIndexed[StepsWidenedFloatArray](_i0, _iN) { - def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsWidenedFloatArray(underlying, i0, half) -} - -private[java8] class StepsDoubleArray(underlying: Array[Double], _i0: Int, _iN: Int) -extends StepsDoubleLikeIndexed[StepsDoubleArray](_i0, _iN) { - def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsDoubleArray(underlying, i0, half) -} - -private[java8] class StepsIntArray(underlying: Array[Int], _i0: Int, _iN: Int) -extends StepsIntLikeIndexed[StepsIntArray](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntArray(underlying, i0, half) -} - -private[java8] class StepsLongArray(underlying: Array[Long], _i0: Int, _iN: Int) -extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { - def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) -} - -////////////////////////// -// Value class adapters // -////////////////////////// - -final class RichArrayCanStep[T](private val underlying: Array[T]) extends AnyVal with MakesStepper[T, EfficientSubstep] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { - case StepperShape.Reference => - if(underlying.isInstanceOf[Array[Boolean]]) - new StepsBoxedBooleanArray (underlying.asInstanceOf[Array[Boolean]], 0, underlying.length) - else new StepsObjectArray[AnyRef](underlying.asInstanceOf[Array[AnyRef ]], 0, underlying.length) - case StepperShape.IntValue => new StepsIntArray (underlying.asInstanceOf[Array[Int ]], 0, underlying.length) - case StepperShape.LongValue => new StepsLongArray (underlying.asInstanceOf[Array[Long ]], 0, underlying.length) - case StepperShape.DoubleValue => new StepsDoubleArray (underlying.asInstanceOf[Array[Double ]], 0, underlying.length) - case StepperShape.ByteValue => new StepsWidenedByteArray (underlying.asInstanceOf[Array[Byte ]], 0, underlying.length) - case StepperShape.ShortValue => new StepsWidenedShortArray (underlying.asInstanceOf[Array[Short ]], 0, underlying.length) - case StepperShape.CharValue => new StepsWidenedCharArray (underlying.asInstanceOf[Array[Char ]], 0, underlying.length) - case StepperShape.FloatValue => new StepsWidenedFloatArray (underlying.asInstanceOf[Array[Float ]], 0, underlying.length) - }).asInstanceOf[S with EfficientSubstep] -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala deleted file mode 100644 index 279035b..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ - -import Stepper._ - -//////////////////////////// -// Stepper implementation // -//////////////////////////// - -private[java8] class StepsIntBitSet(_underlying: Array[Long], _i0: Int, _iN: Int) -extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { - private var mask: Long = (-1L) << (i & 0x3F) - private var cache: Long = underlying(i >>> 6) - private var found: Boolean = false - def semiclone(half: Int) = { - val ans = new StepsIntBitSet(underlying, i, half) - i = half - mask = (-1L) << (i & 0x3F) - cache = underlying(i >>> 6) - found = false - ans - } - def hasNext(): Boolean = found || ((i < iN) && { - while ((mask & cache) == 0) { - i += java.lang.Long.numberOfLeadingZeros(~mask) - if (i < 0 || i >= iN) { i = iN; return false } - mask = -1L - cache = underlying(i >>> 6) - } - var m = mask << 1 - while ((mask & cache) == (m & cache)) { - mask = m - m = mask << 1 - i += 1 - } - if (i < 0 || i >= iN) { - i = iN - false - } - else { - found = true - true - } - }) - def nextInt() = if (hasNext) { val j = i; found = false; mask = mask << 1; i += 1; j } else throwNSEE -} - -///////////////////////// -// Value class adapter // -///////////////////////// - -final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesStepper[Int, EfficientSubstep] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[Int, S]) = { - val bits: Array[Long] = underlying match { - case m: collection.mutable.BitSet => CollectionInternals.getBitSetInternals(m) - case n: collection.immutable.BitSet.BitSetN => RichBitSetCanStep.reflectInternalsN(n) - case x => x.toBitMask - } - new StepsIntBitSet(bits, 0, math.min(bits.length*64L, Int.MaxValue).toInt).asInstanceOf[S with EfficientSubstep] - } -} - -private[java8] object RichBitSetCanStep { - private val reflector = classOf[collection.immutable.BitSet.BitSetN].getMethod("elems") - def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] -} - diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala deleted file mode 100644 index 3ec1ae2..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ - -import Stepper._ - -///////////////////////////// -// Stepper implementations // -///////////////////////////// - -private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) -extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { - def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsAnyFlatHashTable[A](underlying, i0, half) -} - -private[java8] class StepsDoubleFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) -extends StepsDoubleLikeGapped[StepsDoubleFlatHashTable](_underlying, _i0, _iN) { - def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Double]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsDoubleFlatHashTable(underlying, i0, half) -} - -private[java8] class StepsIntFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) -extends StepsIntLikeGapped[StepsIntFlatHashTable](_underlying, _i0, _iN) { - def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Int]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsIntFlatHashTable(underlying, i0, half) -} - -private[java8] class StepsLongFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) -extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { - def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Long]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsLongFlatHashTable(underlying, i0, half) -} - -////////////////////////// -// Value class adapters // -////////////////////////// - -final class RichFlatHashTableCanStep[T](private val underlying: collection.mutable.FlatHashTable[T]) extends AnyVal with MakesStepper[T, EfficientSubstep] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = { - val tbl = CollectionInternals.getTable(underlying) - ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntFlatHashTable (tbl, 0, tbl.length) - case StepperShape.LongValue => new StepsLongFlatHashTable (tbl, 0, tbl.length) - case StepperShape.DoubleValue => new StepsDoubleFlatHashTable(tbl, 0, tbl.length) - case _ => ss.parUnbox(new StepsAnyFlatHashTable[T](tbl, 0, tbl.length)) - }).asInstanceOf[S with EfficientSubstep] - } -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala deleted file mode 100644 index f7a9f6c..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ - -import Stepper._ - -///////////////////////////// -// Stepper implementations // -///////////////////////////// - -// Steppers for keys (type of HashEntry doesn't matter) - -private[java8] class StepsAnyHashTableKey[K](_underlying: Array[collection.mutable.HashEntry[K, _]], _i0: Int, _iN: Int) -extends StepsLikeGapped[K, StepsAnyHashTableKey[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[collection.mutable.HashEntry[K, _]].key; currentEntry = currentEntry.asInstanceOf[collection.mutable.HashEntry[K, _]].next.asInstanceOf[AnyRef]; ans } - def semiclone(half: Int) = new StepsAnyHashTableKey[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, _]]], i0, half) -} - -private[java8] class StepsDoubleHashTableKey(_underlying: Array[collection.mutable.HashEntry[Double, _]], _i0: Int, _iN: Int) -extends StepsDoubleLikeGapped[StepsDoubleHashTableKey](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[collection.mutable.HashEntry[Double, _]].key; currentEntry = currentEntry.asInstanceOf[collection.mutable.HashEntry[Double, _]].next.asInstanceOf[AnyRef]; ans } - def semiclone(half: Int) = new StepsDoubleHashTableKey(underlying.asInstanceOf[Array[collection.mutable.HashEntry[Double, _]]], i0, half) -} - -private[java8] class StepsIntHashTableKey(_underlying: Array[collection.mutable.HashEntry[Int, _]], _i0: Int, _iN: Int) -extends StepsIntLikeGapped[StepsIntHashTableKey](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[collection.mutable.HashEntry[Int, _]].key; currentEntry = currentEntry.asInstanceOf[collection.mutable.HashEntry[Int, _]].next.asInstanceOf[AnyRef]; ans } - def semiclone(half: Int) = new StepsIntHashTableKey(underlying.asInstanceOf[Array[collection.mutable.HashEntry[Int, _]]], i0, half) -} - -private[java8] class StepsLongHashTableKey(_underlying: Array[collection.mutable.HashEntry[Long, _]], _i0: Int, _iN: Int) -extends StepsLongLikeGapped[StepsLongHashTableKey](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[collection.mutable.HashEntry[Long, _]].key; currentEntry = currentEntry.asInstanceOf[collection.mutable.HashEntry[Long, _]].next.asInstanceOf[AnyRef]; ans } - def semiclone(half: Int) = new StepsLongHashTableKey(underlying.asInstanceOf[Array[collection.mutable.HashEntry[Long, _]]], i0, half) -} - -// Steppers for entries stored in DefaultEntry HashEntry -// (both for key-value pair and for values alone) - -private[java8] class StepsAnyDefaultHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) -extends StepsLikeGapped[(K, V), StepsAnyDefaultHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } - def semiclone(half: Int) = - new StepsAnyDefaultHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) -} - -private[java8] class StepsAnyDefaultHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) -extends StepsLikeGapped[V, StepsAnyDefaultHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsAnyDefaultHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) -} - -private[java8] class StepsDoubleDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]], _i0: Int, _iN: Int) -extends StepsDoubleLikeGapped[StepsDoubleDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextDouble() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Double]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsDoubleDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]]], i0, half) -} - -private[java8] class StepsIntDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]], _i0: Int, _iN: Int) -extends StepsIntLikeGapped[StepsIntDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextInt() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Int]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsIntDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]]], i0, half) -} - -private[java8] class StepsLongDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]], _i0: Int, _iN: Int) -extends StepsLongLikeGapped[StepsLongDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextLong() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Long]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsLongDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]]], i0, half) -} - -// Steppers for entries stored in LinkedEntry HashEntry -// (both for key-value pair and for values alone) - -private[java8] class StepsAnyLinkedHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) -extends StepsLikeGapped[(K, V), StepsAnyLinkedHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } - def semiclone(half: Int) = - new StepsAnyLinkedHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) -} - -private[java8] class StepsAnyLinkedHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) -extends StepsLikeGapped[V, StepsAnyLinkedHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsAnyLinkedHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) -} - -private[java8] class StepsDoubleLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]], _i0: Int, _iN: Int) -extends StepsDoubleLikeGapped[StepsDoubleLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextDouble() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Double]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsDoubleLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]]], i0, half) -} - -private[java8] class StepsIntLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]], _i0: Int, _iN: Int) -extends StepsIntLikeGapped[StepsIntLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextInt() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Int]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsIntLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]]], i0, half) -} - -private[java8] class StepsLongLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]], _i0: Int, _iN: Int) -extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextLong() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Long]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsLongLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]]], i0, half) -} - - -////////////////////////// -// Value class adapters // -////////////////////////// - -// Steppers for entries stored in DefaultEntry HashEntry - -final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal with MakesKeyValueStepper[K, V, EfficientSubstep] with MakesStepper[(K, V), EfficientSubstep] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = { - val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) - new StepsAnyDefaultHashTable(tbl, 0, tbl.length).asInstanceOf[S with EfficientSubstep] - } - - def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = { - val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) - ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Int, _]]], 0, tbl.length) - case StepperShape.LongValue => new StepsLongHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Long, _]]], 0, tbl.length) - case StepperShape.DoubleValue => new StepsDoubleHashTableKey(tbl.asInstanceOf[Array[collection.mutable.HashEntry[Double, _]]], 0, tbl.length) - case _ => ss.parUnbox(new StepsAnyHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, _]]], 0, tbl.length)) - }).asInstanceOf[S with EfficientSubstep] - } - - def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = { - val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) - ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntDefaultHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int ]]]], 0, tbl.length) - case StepperShape.LongValue => new StepsLongDefaultHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long ]]]], 0, tbl.length) - case StepperShape.DoubleValue => new StepsDoubleDefaultHashTableValue(tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]]], 0, tbl.length) - case _ => ss.parUnbox(new StepsAnyDefaultHashTableValue (tbl, 0, tbl.length)) - }).asInstanceOf[S with EfficientSubstep] - } -} - -// Steppers for entries stored in LinkedEntry HashEntry - -final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal with MakesKeyValueStepper[K, V, EfficientSubstep] with MakesStepper[(K, V), EfficientSubstep] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = { - val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) - new StepsAnyLinkedHashTable(tbl, 0, tbl.length).asInstanceOf[S with EfficientSubstep] - } - - def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = { - val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) - ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Int, _]]], 0, tbl.length) - case StepperShape.LongValue => new StepsLongHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Long, _]]], 0, tbl.length) - case StepperShape.DoubleValue => new StepsDoubleHashTableKey(tbl.asInstanceOf[Array[collection.mutable.HashEntry[Double, _]]], 0, tbl.length) - case _ => ss.parUnbox(new StepsAnyHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, _]]], 0, tbl.length)) - }).asInstanceOf[S with EfficientSubstep] - } - - def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = { - val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) - ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntLinkedHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int ]]]], 0, tbl.length) - case StepperShape.LongValue => new StepsLongLinkedHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long ]]]], 0, tbl.length) - case StepperShape.DoubleValue => new StepsDoubleLinkedHashTableValue(tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]]], 0, tbl.length) - case _ => ss.parUnbox(new StepsAnyLinkedHashTableValue (tbl, 0, tbl.length)) - }).asInstanceOf[S with EfficientSubstep] - } -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala deleted file mode 100644 index 0b7c329..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.compat.java8.collectionImpl._ - -import Stepper._ - -// Note that there are separate implementations for keys, values, and key-value pairs - -///////////////////////////// -// Stepper implementations // -///////////////////////////// - -private[java8] class StepsAnyImmHashMap[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) -extends StepsLikeImmHashMap[K, V, (K, V), StepsAnyImmHashMap[K, V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMap[K, V](u, j0, jN) - def next(): (K, V) = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.iterator - i += 1 - theIterator.next - } - else throwNSEE -} - -private[java8] class StepsAnyImmHashMapKey[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) -extends StepsLikeImmHashMap[K, V, K, StepsAnyImmHashMapKey[K, V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapKey[K, V](u, j0, jN) - def next(): K = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE -} - -private[java8] class StepsAnyImmHashMapValue[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) -extends StepsLikeImmHashMap[K, V, V, StepsAnyImmHashMapValue[K, V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapValue[K, V](u, j0, jN) - def next(): V = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE -} - -private[java8] class StepsDoubleImmHashMapKey[V](_underlying: collection.immutable.HashMap[Double, V], _i0: Int, _iN: Int) -extends StepsDoubleLikeImmHashMap[Double, V, StepsDoubleImmHashMapKey[V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[Double,V], j0: Int, jN: Int) = new StepsDoubleImmHashMapKey[V](u, j0, jN) - def nextDouble() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE -} - -private[java8] class StepsDoubleImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Double], _i0: Int, _iN: Int) -extends StepsDoubleLikeImmHashMap[K, Double, StepsDoubleImmHashMapValue[K]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,Double], j0: Int, jN: Int) = new StepsDoubleImmHashMapValue[K](u, j0, jN) - def nextDouble() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE -} - -private[java8] class StepsIntImmHashMapKey[V](_underlying: collection.immutable.HashMap[Int, V], _i0: Int, _iN: Int) -extends StepsIntLikeImmHashMap[Int, V, StepsIntImmHashMapKey[V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[Int,V], j0: Int, jN: Int) = new StepsIntImmHashMapKey[V](u, j0, jN) - def nextInt() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE -} - -private[java8] class StepsIntImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Int], _i0: Int, _iN: Int) -extends StepsIntLikeImmHashMap[K, Int, StepsIntImmHashMapValue[K]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,Int], j0: Int, jN: Int) = new StepsIntImmHashMapValue[K](u, j0, jN) - def nextInt() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE -} - -private[java8] class StepsLongImmHashMapKey[V](_underlying: collection.immutable.HashMap[Long, V], _i0: Int, _iN: Int) -extends StepsLongLikeImmHashMap[Long, V, StepsLongImmHashMapKey[V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[Long,V], j0: Int, jN: Int) = new StepsLongImmHashMapKey[V](u, j0, jN) - def nextLong() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE -} - -private[java8] class StepsLongImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Long], _i0: Int, _iN: Int) -extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,Long], j0: Int, jN: Int) = new StepsLongImmHashMapValue[K](u, j0, jN) - def nextLong() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE -} - -////////////////////////// -// Value class adapters // -////////////////////////// - -final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) extends AnyVal with MakesKeyValueStepper[K, V, EfficientSubstep] with MakesStepper[(K, V), EfficientSubstep] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = - new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size).asInstanceOf[S with EfficientSubstep] - - def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntImmHashMapKey (underlying.asInstanceOf[collection.immutable.HashMap[Int, V]], 0, underlying.size) - case StepperShape.LongValue => new StepsLongImmHashMapKey (underlying.asInstanceOf[collection.immutable.HashMap[Long, V]], 0, underlying.size) - case StepperShape.DoubleValue => new StepsDoubleImmHashMapKey (underlying.asInstanceOf[collection.immutable.HashMap[Double, V]], 0, underlying.size) - case _ => ss.parUnbox(new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size)) - }).asInstanceOf[S with EfficientSubstep] - - def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntImmHashMapValue (underlying.asInstanceOf[collection.immutable.HashMap[K, Int]], 0, underlying.size) - case StepperShape.LongValue => new StepsLongImmHashMapValue (underlying.asInstanceOf[collection.immutable.HashMap[K, Long]], 0, underlying.size) - case StepperShape.DoubleValue => new StepsDoubleImmHashMapValue (underlying.asInstanceOf[collection.immutable.HashMap[K, Double]], 0, underlying.size) - case _ => ss.parUnbox(new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size)) - }).asInstanceOf[S with EfficientSubstep] -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala deleted file mode 100644 index 864a3c2..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.compat.java8.collectionImpl._ - -///////////////////////////// -// Stepper implementations // -///////////////////////////// - -private[java8] class StepsAnyImmHashSet[A](_underlying: Iterator[A], _N: Int) -extends StepsLikeTrieIterator[A, StepsAnyImmHashSet[A]](_underlying, _N) { - protected def demiclone(it: Iterator[A], N: Int) = new StepsAnyImmHashSet(it, N) - def next(): A = { val ans = underlying.next; i += 1; ans } -} - -private[java8] class StepsDoubleImmHashSet(_underlying: Iterator[Double], _N: Int) -extends StepsDoubleLikeTrieIterator[StepsDoubleImmHashSet](_underlying, _N) { - protected def demiclone(it: Iterator[Double], N: Int) = new StepsDoubleImmHashSet(it, N) - def nextDouble() = { val ans = underlying.next; i += 1; ans } -} - -private[java8] class StepsIntImmHashSet(_underlying: Iterator[Int], _N: Int) -extends StepsIntLikeTrieIterator[StepsIntImmHashSet](_underlying, _N) { - protected def demiclone(it: Iterator[Int], N: Int) = new StepsIntImmHashSet(it, N) - def nextInt() = { val ans = underlying.next; i += 1; ans } -} - -private[java8] class StepsLongImmHashSet(_underlying: Iterator[Long], _N: Int) -extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { - protected def demiclone(it: Iterator[Long], N: Int) = new StepsLongImmHashSet(it, N) - def nextLong() = { val ans = underlying.next; i += 1; ans } -} - -////////////////////////// -// Value class adapters // -////////////////////////// - -final class RichImmHashSetCanStep[T](private val underlying: collection.immutable.HashSet[T]) extends AnyVal with MakesStepper[T, EfficientSubstep] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntImmHashSet (underlying.iterator.asInstanceOf[Iterator[Int]], underlying.size) - case StepperShape.LongValue => new StepsLongImmHashSet (underlying.iterator.asInstanceOf[Iterator[Long]], underlying.size) - case StepperShape.DoubleValue => new StepsDoubleImmHashSet(underlying.iterator.asInstanceOf[Iterator[Double]], underlying.size) - case _ => ss.parUnbox(new StepsAnyImmHashSet[T](underlying.iterator, underlying.size)) - }).asInstanceOf[S with EfficientSubstep] -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala deleted file mode 100644 index b7d2fe7..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.compat.java8.collectionImpl._ - -import Stepper._ - -///////////////////////////// -// Stepper implementations // -///////////////////////////// - -private[java8] class StepsAnyIndexedSeq[A](underlying: collection.IndexedSeqLike[A, _], _i0: Int, _iN: Int) -extends StepsLikeIndexed[A, StepsAnyIndexedSeq[A]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyIndexedSeq[A](underlying, i0, half) -} - -private[java8] class StepsDoubleIndexedSeq[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC, _i0: Int, _iN: Int) -extends StepsDoubleLikeIndexed[StepsDoubleIndexedSeq[CC]](_i0, _iN) { - def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsDoubleIndexedSeq[CC](underlying, i0, half) -} - -private[java8] class StepsIntIndexedSeq[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC, _i0: Int, _iN: Int) -extends StepsIntLikeIndexed[StepsIntIndexedSeq[CC]](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntIndexedSeq[CC](underlying, i0, half) -} - -private[java8] class StepsLongIndexedSeq[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC, _i0: Int, _iN: Int) -extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { - def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsLongIndexedSeq[CC](underlying, i0, half) -} - -////////////////////////// -// Value class adapters // -////////////////////////// - -final class RichIndexedSeqCanStep[T](private val underlying: collection.IndexedSeqLike[T, _]) extends AnyVal with MakesStepper[T, EfficientSubstep] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntIndexedSeq (underlying.asInstanceOf[collection.IndexedSeqLike[Int, _]], 0, underlying.length) - case StepperShape.LongValue => new StepsLongIndexedSeq (underlying.asInstanceOf[collection.IndexedSeqLike[Long, _]], 0, underlying.length) - case StepperShape.DoubleValue => new StepsDoubleIndexedSeq(underlying.asInstanceOf[collection.IndexedSeqLike[Double, _]], 0, underlying.length) - case _ => ss.parUnbox(new StepsAnyIndexedSeq[T](underlying, 0, underlying.length)) - }).asInstanceOf[S with EfficientSubstep] -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala deleted file mode 100644 index 4343206..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.compat.java8.collectionImpl._ - -// Iterables just defer to iterator unless they can pattern match something better. -// TODO: implement pattern matching! - -final class RichIterableCanStep[T](private val underlying: Iterable[T]) extends AnyVal with MakesStepper[T, Any] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntIterator (underlying.iterator.asInstanceOf[Iterator[Int]]) - case StepperShape.LongValue => new StepsLongIterator (underlying.iterator.asInstanceOf[Iterator[Long]]) - case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.iterator.asInstanceOf[Iterator[Double]]) - case _ => ss.seqUnbox(new StepsAnyIterator[T](underlying.iterator)) - }).asInstanceOf[S] -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala deleted file mode 100644 index 62549a1..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.compat.java8.collectionImpl._ - -///////////////////////////// -// Stepper implementations // -///////////////////////////// - -private[java8] class StepsAnyIterator[A](_underlying: Iterator[A]) -extends StepsLikeIterator[A, StepsAnyIterator[A]](_underlying) { - def semiclone() = new StepsAnyIterator(null) - def next() = if (proxied ne null) proxied.nextStep else underlying.next -} - -private[java8] class StepsDoubleIterator(_underlying: Iterator[Double]) -extends StepsDoubleLikeIterator[StepsDoubleIterator](_underlying) { - def semiclone() = new StepsDoubleIterator(null) - def nextDouble() = if (proxied ne null) proxied.nextStep else underlying.next -} - -private[java8] class StepsIntIterator(_underlying: Iterator[Int]) -extends StepsIntLikeIterator[StepsIntIterator](_underlying) { - def semiclone() = new StepsIntIterator(null) - def nextInt() = if (proxied ne null) proxied.nextStep else underlying.next -} - -private[java8] class StepsLongIterator(_underlying: Iterator[Long]) -extends StepsLongLikeIterator[StepsLongIterator](_underlying) { - def semiclone() = new StepsLongIterator(null) - def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next -} - -////////////////////////// -// Value class adapters // -////////////////////////// - -final class RichIteratorCanStep[T](private val underlying: Iterator[T]) extends AnyVal with MakesStepper[T, Any] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntIterator (underlying.asInstanceOf[Iterator[Int]]) - case StepperShape.LongValue => new StepsLongIterator (underlying.asInstanceOf[Iterator[Long]]) - case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.asInstanceOf[Iterator[Double]]) - case _ => ss.seqUnbox(new StepsAnyIterator[T](underlying)) - }).asInstanceOf[S] -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala deleted file mode 100644 index 27c3bff..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.compat.java8.collectionImpl._ -import Stepper._ - -/** Abstracts all the generic operations of stepping over a backing array - * for some collection where the elements are stored generically and some - * may be missing. Subclasses should set `currentEntry` to `null` when it - * is used as a signal to look for more entries in the array. (This also - * allows a subclass to traverse a sublist by updating `currentEntry`.) - */ -private[java8] abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub](protected val underlying: Array[AnyRef], protected var i0: Int, protected var iN: Int) - extends EfficientSubstep { - - protected var currentEntry: AnyRef = null - def semiclone(half: Int): Semi - def characteristics(): Int = Ordered - def estimateSize(): Long = if (!hasNext) 0 else iN - i0 - def hasNext(): Boolean = currentEntry != null || (i0 < iN && { - do { currentEntry = underlying(i0); i0 += 1 } while (currentEntry == null && i0 < iN) - currentEntry != null - }) - def substep(): Sub = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = semiclone(half) - i0 = half - ans - } - else null - } -} - -/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` - * and interpreting the contents as the elements of a collection. - */ -private[java8] abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends AbstractStepsLikeGapped[AnyStepper[A], STA](_underlying, _i0, _iN) - with AnyStepper[A] -{} - -/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` - * and interpreting the contents as the elements of a collection of `Double`s. Subclasses - * are responsible for unboxing the `AnyRef` inside `nextDouble`. - */ -private[java8] abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends AbstractStepsLikeGapped[DoubleStepper, STD](_underlying, _i0, _iN) - with DoubleStepper -{} - -/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` - * and interpreting the contents as the elements of a collection of `Int`s. Subclasses - * are responsible for unboxing the `AnyRef` inside `nextInt`. - */ -private[java8] abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends AbstractStepsLikeGapped[IntStepper, STI](_underlying, _i0, _iN) - with IntStepper -{} - -/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` - * and interpreting the contents as the elements of a collection of `Long`s. Subclasses - * are responsible for unboxing the `AnyRef` inside `nextLong`. - */ -private[java8] abstract class StepsLongLikeGapped[STL >: Null <: StepsLongLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends AbstractStepsLikeGapped[LongStepper, STL](_underlying, _i0, _iN) - with LongStepper -{} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala deleted file mode 100644 index e7ced1a..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.compat.java8.collectionImpl._ -import Stepper._ - -/** Abstracts all the generic operations of stepping over an immutable HashMap by slicing it into pieces. - * `next` must update `i` but not `i0` so that later splitting steps can keep track of whether the - * collection needs some sort of modification before transmission to the subclass. - */ -private[java8] trait AbstractStepsLikeImmHashMap[K, V, A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeImmHashMap[K, V, A, Sub, _]] -extends AbstractStepsLikeSliced[collection.immutable.HashMap[K, V], Sub, Semi] { - protected var theIterator: Iterator[A] = null - protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int): Semi - override def characteristics() = Immutable - def hasNext(): Boolean = i < iN - def semiclone(halfHint: Int): Semi = - if (i >= iN) null - else underlying match { - case trie: collection.immutable.HashMap.HashTrieMap[K, V] => - val parts = if (i > i0) trie.drop(i-i0).split else trie.split - if (parts.length != 2) null - else { - val ans = demiclone(parts.head, 0, parts.head.size) - i = iN - parts.last.size - underlying = parts.last - ans.theIterator = theIterator - theIterator = null - i0 = i - ans - } - case _ => null - } -} - -private[java8] abstract class StepsLikeImmHashMap[K, V, A, SIHM >: Null <: StepsLikeImmHashMap[K, V, A, _]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) - extends StepsLikeSliced[A, collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) - with AbstractStepsLikeImmHashMap[K, V, A, AnyStepper[A], SIHM] -{} - -private[java8] abstract class StepsDoubleLikeImmHashMap[K, V, SIHM >: Null <: StepsDoubleLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) - extends StepsDoubleLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) - with AbstractStepsLikeImmHashMap[K, V, Double, DoubleStepper, SIHM] -{} - -private[java8] abstract class StepsIntLikeImmHashMap[K, V, SIHM >: Null <: StepsIntLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) - extends StepsIntLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) - with AbstractStepsLikeImmHashMap[K, V, Int, IntStepper, SIHM] -{} - -private[java8] abstract class StepsLongLikeImmHashMap[K, V, SIHM >: Null <: StepsLongLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) - extends StepsLongLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) - with AbstractStepsLikeImmHashMap[K, V, Long, LongStepper, SIHM] -{} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala deleted file mode 100644 index 325b064..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.compat.java8.collectionImpl._ -import Stepper._ - -/** Abstracts all the generic operations of stepping over an indexable collection */ -private[java8] abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var i0: Int, protected var iN: Int) - extends EfficientSubstep { - - def semiclone(half: Int): Semi - def characteristics(): Int = Ordered + Sized + SubSized - def estimateSize(): Long = iN - i0 - def hasNext(): Boolean = i0 < iN - def substep(): Sub = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = semiclone(half) - i0 = half - ans - } - else null - } -} - -/** Abstracts the operation of stepping over a generic indexable collection */ -private[java8] abstract class StepsLikeIndexed[A, STA >: Null <: StepsLikeIndexed[A, _]](_i0: Int, _iN: Int) - extends AbstractStepsLikeIndexed[AnyStepper[A], STA](_i0, _iN) - with AnyStepper[A] -{} - -/** Abstracts the operation of stepping over an indexable collection of Doubles */ -private[java8] abstract class StepsDoubleLikeIndexed[STD >: Null <: StepsDoubleLikeIndexed[_]](_i0: Int, _iN: Int) - extends AbstractStepsLikeIndexed[DoubleStepper, STD](_i0, _iN) - with DoubleStepper - with java.util.Spliterator.OfDouble // Compiler wants this for mixin forwarder -{} - -/** Abstracts the operation of stepping over an indexable collection of Ints */ -private[java8] abstract class StepsIntLikeIndexed[STI >: Null <: StepsIntLikeIndexed[_]](_i0: Int, _iN: Int) - extends AbstractStepsLikeIndexed[IntStepper, STI](_i0, _iN) - with IntStepper - with java.util.Spliterator.OfInt // Compiler wants this for mixin forwarder -{} - -/** Abstracts the operation of stepping over an indexable collection of Longs */ -private[java8] abstract class StepsLongLikeIndexed[STL >: Null <: StepsLongLikeIndexed[_]](_i0: Int, _iN: Int) - extends AbstractStepsLikeIndexed[LongStepper, STL](_i0, _iN) - with LongStepper - with java.util.Spliterator.OfLong // Compiler wants this for mixin forwarder -{} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala deleted file mode 100644 index 518cee3..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.compat.java8.collectionImpl._ -import Stepper._ - -/** Common functionality for Steppers that step through an Iterator, caching the results as needed when a split is requested. */ -private[java8] abstract class AbstractStepsLikeIterator[A, SP >: Null <: Stepper[A], Semi <: SP](final protected var underlying: Iterator[A]) { - final protected var nextChunkSize = 16 - final protected var proxied: SP = null - def semiclone(): Semi // Must initialize with null iterator! - def characteristics(): Int = if (proxied ne null) Ordered | Sized | SubSized else Ordered - def estimateSize(): Long = if (proxied ne null) proxied.knownSize else Long.MaxValue - def hasNext(): Boolean = if (proxied ne null) proxied.hasStep else underlying.hasNext -} - -/** Abstracts the operation of stepping over an iterator (that needs to be cached when splitting) */ -private[java8] abstract class StepsLikeIterator[A, SLI >: Null <: StepsLikeIterator[A, SLI] with AnyStepper[A]](_underlying: Iterator[A]) - extends AbstractStepsLikeIterator[A, AnyStepper[A], SLI](_underlying) - with AnyStepper[A] -{ - override def substep(): AnyStepper[A] = if (proxied ne null) proxied.substep else { - val acc = new Accumulator[A] - var i = 0 - val n = (nextChunkSize & 0xFFFFFFFC) - while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } - if (i < n || !underlying.hasNext) { - proxied = acc.stepper - proxied.substep - } - else { - val ans = semiclone() - ans.proxied = acc.stepper - nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 - ans - } - } -} - -/** Abstracts the operation of stepping over an iterator of Doubles (needs caching when split) */ -private[java8] abstract class StepsDoubleLikeIterator[SLI >: Null <: StepsDoubleLikeIterator[SLI] with DoubleStepper](_underlying: Iterator[Double]) - extends AbstractStepsLikeIterator[Double, DoubleStepper, SLI](_underlying) - with DoubleStepper -{ - override def substep(): DoubleStepper = if (proxied ne null) proxied.substep else { - val acc = new DoubleAccumulator - var i = 0 - val n = (nextChunkSize & 0xFFFFFFFC) - while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } - if (i < n || !underlying.hasNext) { - proxied = acc.stepper - proxied.substep - } - else { - val ans = semiclone() - ans.proxied = acc.stepper - nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 - ans - } - } -} - -/** Abstracts the operation of stepping over an iterator of Ints (needs caching when split) */ -private[java8] abstract class StepsIntLikeIterator[SLI >: Null <: StepsIntLikeIterator[SLI] with IntStepper](_underlying: Iterator[Int]) - extends AbstractStepsLikeIterator[Int, IntStepper, SLI](_underlying) - with IntStepper -{ - override def substep(): IntStepper = if (proxied ne null) proxied.substep else { - val acc = new IntAccumulator - var i = 0 - val n = (nextChunkSize & 0xFFFFFFFC) - while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } - if (i < n || !underlying.hasNext) { - proxied = acc.stepper - proxied.substep - } - else { - val ans = semiclone() - ans.proxied = acc.stepper - nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 - ans - } - } -} - -/** Abstracts the operation of stepping over an iterator of Longs (needs caching when split) */ -private[java8] abstract class StepsLongLikeIterator[SLI >: Null <: StepsLongLikeIterator[SLI] with LongStepper](_underlying: Iterator[Long]) - extends AbstractStepsLikeIterator[Long, LongStepper, SLI](_underlying) - with LongStepper -{ - override def substep: LongStepper = if (proxied ne null) proxied.substep else { - val acc = new LongAccumulator - var i = 0 - val n = (nextChunkSize & 0xFFFFFFFC) - while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } - if (i < n || !underlying.hasNext) { - proxied = acc.stepper - proxied.substep - } - else { - val ans = semiclone() - ans.proxied = acc.stepper - nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 - ans - } - } -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala deleted file mode 100644 index ed3c695..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.compat.java8.collectionImpl._ -import Stepper._ - -/** Abstracts all the generic operations of stepping over a collection that can be sliced into pieces. - * `next` must update `i` but not `i0` so that later splitting steps can keep track of whether the - * collection needs some sort of modification before transmission to the subclass. - */ -private[java8] abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected var underlying: Coll, protected var i: Int, protected var iN: Int) - extends EfficientSubstep { - - protected var i0: Int = i - def semiclone(halfHint: Int): Semi // Must really do all the work for both this and cloned collection! - def characteristics(): Int = Ordered - def estimateSize(): Long = iN - i - def substep(): Sub = if (estimateSize > 0) semiclone((iN + i) >>> 1) else null -} - -/** Abstracts the operation of stepping over a generic collection that can be efficiently sliced or otherwise subdivided */ -private[java8] abstract class StepsLikeSliced[A, AA, STA >: Null <: StepsLikeSliced[A, AA, _]](_underlying: AA, _i0: Int, _iN: Int) - extends AbstractStepsLikeSliced[AA, AnyStepper[A], STA](_underlying, _i0, _iN) - with AnyStepper[A] -{} - -/** Abstracts the operation of stepping over a collection of Doubles that can be efficiently sliced or otherwise subdivided */ -private[java8] abstract class StepsDoubleLikeSliced[AA, STA >: Null <: StepsDoubleLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) - extends AbstractStepsLikeSliced[AA, DoubleStepper, STA](_underlying, _i0, _iN) - with DoubleStepper -{} - -/** Abstracts the operation of stepping over a collection of Ints that can be efficiently sliced or otherwise subdivided */ -private[java8] abstract class StepsIntLikeSliced[AA, STA >: Null <: StepsIntLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) - extends AbstractStepsLikeSliced[AA, IntStepper, STA](_underlying, _i0, _iN) - with IntStepper -{} - -/** Abstracts the operation of stepping over a collection of Longs that can be efficiently sliced or otherwise subdivided */ -private[java8] abstract class StepsLongLikeSliced[AA, STA >: Null <: StepsLongLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) - extends AbstractStepsLikeSliced[AA, LongStepper, STA](_underlying, _i0, _iN) - with LongStepper -{} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala deleted file mode 100644 index 78abd12..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.compat.java8.collectionImpl._ -import Stepper._ - -/** Abstracts all the generic operations of stepping over a TrieIterator by asking itself to - * slice itself into pieces. Note that `i` must be kept up to date in subclasses. - */ -private[java8] trait AbstractStepsLikeTrieIterator[A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeTrieIterator[A, Sub, _]] -extends AbstractStepsLikeSliced[Iterator[A], Sub, Semi] { - protected def demiclone(it: Iterator[A], N: Int): Semi - override def characteristics() = Immutable - def hasNext(): Boolean = underlying.hasNext - def semiclone(halfHint: Int): Semi = - if (!underlying.hasNext || i > iN-2) null - else scala.compat.java8.runtime.CollectionInternals.trieIteratorSplit(underlying) match { - case null => null - case ((pre: Iterator[A], pno), post: Iterator[A]) => - val pn = (pno: Any) match { case i: Int => i; case _ => throw new Exception("Unexpected type") } - val ans = demiclone(pre, pn) - i += pn - underlying = post - i0 = i - ans - case _ => null - } -} - -private[java8] abstract class StepsLikeTrieIterator[A, STI >: Null <: StepsLikeTrieIterator[A, _]](_underlying: Iterator[A], _N: Int) - extends StepsLikeSliced[A, Iterator[A], STI](_underlying, 0, _N) - with AbstractStepsLikeTrieIterator[A, AnyStepper[A], STI] -{} - -private[java8] abstract class StepsDoubleLikeTrieIterator[STI >: Null <: StepsDoubleLikeTrieIterator[STI]](_underlying: Iterator[Double], _N: Int) - extends StepsDoubleLikeSliced[Iterator[Double], STI](_underlying, 0, _N) - with AbstractStepsLikeTrieIterator[Double, DoubleStepper, STI] -{} - -private[java8] abstract class StepsIntLikeTrieIterator[STI >: Null <: StepsIntLikeTrieIterator[STI]](_underlying: Iterator[Int], _N: Int) - extends StepsIntLikeSliced[Iterator[Int], STI](_underlying, 0, _N) - with AbstractStepsLikeTrieIterator[Int, IntStepper, STI] -{} - -private[java8] abstract class StepsLongLikeTrieIterator[STI >: Null <: StepsLongLikeTrieIterator[STI]](_underlying: Iterator[Long], _N: Int) - extends StepsLongLikeSliced[Iterator[Long], STI](_underlying, 0, _N) - with AbstractStepsLikeTrieIterator[Long, LongStepper, STI] -{} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala deleted file mode 100644 index d78c893..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.compat.java8.collectionImpl._ - -import Stepper._ - -///////////////////////////// -// Stepper implementations // -///////////////////////////// - -private[java8] class StepsAnyLinearSeq[A](_underlying: collection.LinearSeq[A], _maxN: Long) -extends StepsWithTail[A, collection.LinearSeq[A], StepsAnyLinearSeq[A]](_underlying, _maxN) { - protected def myIsEmpty(cc: collection.LinearSeq[A]): Boolean = cc.isEmpty - protected def myTailOf(cc: collection.LinearSeq[A]) = cc.tail - def next() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsAnyLinearSeq[A](underlying, half) -} - -private[java8] class StepsDoubleLinearSeq(_underlying: collection.LinearSeq[Double], _maxN: Long) -extends StepsDoubleWithTail[collection.LinearSeq[Double], StepsDoubleLinearSeq](_underlying, _maxN) { - protected def myIsEmpty(cc: collection.LinearSeq[Double]): Boolean = cc.isEmpty - protected def myTailOf(cc: collection.LinearSeq[Double]) = cc.tail - def nextDouble() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsDoubleLinearSeq(underlying, half) -} - -private[java8] class StepsIntLinearSeq(_underlying: collection.LinearSeq[Int], _maxN: Long) -extends StepsIntWithTail[collection.LinearSeq[Int], StepsIntLinearSeq](_underlying, _maxN) { - protected def myIsEmpty(cc: collection.LinearSeq[Int]): Boolean = cc.isEmpty - protected def myTailOf(cc: collection.LinearSeq[Int]) = cc.tail - def nextInt() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsIntLinearSeq(underlying, half) -} - -private[java8] class StepsLongLinearSeq(_underlying: collection.LinearSeq[Long], _maxN: Long) -extends StepsLongWithTail[collection.LinearSeq[Long], StepsLongLinearSeq](_underlying, _maxN) { - protected def myIsEmpty(cc: collection.LinearSeq[Long]): Boolean = cc.isEmpty - protected def myTailOf(cc: collection.LinearSeq[Long]) = cc.tail - def nextLong() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsLongLinearSeq(underlying, half) -} - -////////////////////////// -// Value class adapters // -////////////////////////// - -final class RichLinearSeqCanStep[T](private val underlying: collection.LinearSeq[T]) extends AnyVal with MakesStepper[T, Any] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntLinearSeq (underlying.asInstanceOf[collection.LinearSeq[Int]], Long.MaxValue) - case StepperShape.LongValue => new StepsLongLinearSeq (underlying.asInstanceOf[collection.LinearSeq[Long]], Long.MaxValue) - case StepperShape.DoubleValue => new StepsDoubleLinearSeq(underlying.asInstanceOf[collection.LinearSeq[Double]], Long.MaxValue) - case _ => ss.seqUnbox(new StepsAnyLinearSeq[T](underlying, Long.MaxValue)) - }).asInstanceOf[S] -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala deleted file mode 100644 index c6e8862..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.compat.java8.collectionImpl._ - -// Generic maps defer to the iterator steppers if a more precise type cannot be found via pattern matching -// TODO: implement pattern matching - -final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesKeyValueStepper[K, V, Any] { - // No generic stepper because RichIterableCanStep will get that anyway, and we don't pattern match here - - def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntIterator (underlying.keysIterator.asInstanceOf[Iterator[Int]]) - case StepperShape.LongValue => new StepsLongIterator (underlying.keysIterator.asInstanceOf[Iterator[Long]]) - case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.keysIterator.asInstanceOf[Iterator[Double]]) - case _ => ss.seqUnbox(new StepsAnyIterator (underlying.keysIterator)) - }).asInstanceOf[S] - - def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntIterator (underlying.valuesIterator.asInstanceOf[Iterator[Int]]) - case StepperShape.LongValue => new StepsLongIterator (underlying.valuesIterator.asInstanceOf[Iterator[Long]]) - case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.valuesIterator.asInstanceOf[Iterator[Double]]) - case _ => ss.seqUnbox(new StepsAnyIterator (underlying.valuesIterator)) - }).asInstanceOf[S] -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala deleted file mode 100644 index a4c92a3..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.compat.java8.collectionImpl._ - -import Stepper._ - -///////////////////////////// -// Stepper implementations // -///////////////////////////// - -private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) -extends StepsIntLikeIndexed[StepsIntRange](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntRange(underlying, i0, half) -} - -private[java8] class StepsAnyNumericRange[T](underlying: collection.immutable.NumericRange[T], _i0: Int, _iN: Int) -extends StepsLikeIndexed[T, StepsAnyNumericRange[T]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyNumericRange[T](underlying, i0, half) -} - -private[java8] class StepsIntNumericRange(underlying: collection.immutable.NumericRange[Int], _i0: Int, _iN: Int) -extends StepsIntLikeIndexed[StepsIntNumericRange](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntNumericRange(underlying, i0, half) -} - -private[java8] class StepsLongNumericRange(underlying: collection.immutable.NumericRange[Long], _i0: Int, _iN: Int) -extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { - def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsLongNumericRange(underlying, i0, half) -} - -////////////////////////// -// Value class adapters // -////////////////////////// - -final class RichRangeCanStep[T](private val underlying: Range) extends AnyVal with MakesStepper[Int, EfficientSubstep] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[Int, S]) = - new StepsIntRange(underlying, 0, underlying.length).asInstanceOf[S with EfficientSubstep] -} - -final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesStepper[T, EfficientSubstep] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntNumericRange (underlying.asInstanceOf[collection.immutable.NumericRange[Int]], 0, underlying.length) - case StepperShape.LongValue => new StepsLongNumericRange (underlying.asInstanceOf[collection.immutable.NumericRange[Long]], 0, underlying.length) - case _ => ss.parUnbox(new StepsAnyNumericRange[T](underlying, 0, underlying.length)) - }).asInstanceOf[S with EfficientSubstep] -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala deleted file mode 100644 index adc78f7..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.compat.java8.collectionImpl._ - -import Stepper._ - -//////////////////////////// -// Stepper implementation // -//////////////////////////// - -private[java8] class StepperStringChar(underlying: CharSequence, _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepperStringChar](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying.charAt(j) } else throwNSEE - def semiclone(half: Int) = new StepperStringChar(underlying, i0, half) -} - -private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper with EfficientSubstep { - def characteristics() = NonNull - def estimateSize = iN - i0 - def hasNext = i0 < iN - def nextInt() = { - if (hasNext()) { - val cp = underlying.codePointAt(i0) - i0 += java.lang.Character.charCount(cp) - cp - } - else throwNSEE - } - def substep() = { - if (iN-3 > i0) { - var half = (i0+iN) >>> 1 - if (java.lang.Character.isLowSurrogate(underlying.charAt(half))) half -= 1 - val ans = new StepperStringCodePoint(underlying, i0, half) - i0 = half - ans - } - else null - } -} - -///////////////////////// -// Value class adapter // -///////////////////////// - -final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesStepper[Char, EfficientSubstep] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[Char, S]) = charStepper.asInstanceOf[S with EfficientSubstep] - @inline def charStepper: IntStepper with EfficientSubstep = new StepperStringChar(underlying, 0, underlying.length) - @inline def codepointStepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala deleted file mode 100644 index 0c9a23e..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.annotation.switch - -import scala.collection.immutable.VectorIterator - -import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ - -import Stepper._ - -///////////////////////////// -// Stepper implementations // -///////////////////////////// - -private[java8] trait StepsVectorLike[A] { - protected def myVector: Vector[A] - protected def myVectorIterator: VectorIterator[A] - protected def myVectorLength: Int - protected var index: Int = 32 - protected var data: Array[AnyRef] = null - protected var index1: Int = 32 - protected var data1: Array[AnyRef] = null - protected final def advanceData(iX: Int): Unit = { - index1 += 1 - if (index >= 32) { - if (myVector != null) initTo(iX) - else initVpTo(iX) - } - else { - data = data1(index1).asInstanceOf[Array[AnyRef]] - index = 0 - } - } - protected final def initTo(iX: Int): Unit = { - // WARNING--initVpTo is an exact copy of this except for the type! If you change one you must change the other! - // (Manually specialized this way for speed.) - myVectorLength match { - case x if x <= 0x20 => - index = iX - data = CollectionInternals.getDisplay0(myVector) - case x if x <= 0x400 => - index1 = iX >>> 5 - data1 = CollectionInternals.getDisplay1(myVector) - index = iX & 0x1F - data = data1(index1).asInstanceOf[Array[AnyRef]] - case x => - var N = 0 - var dataN: Array[AnyRef] = - if (x <= 0x8000) { N = 2; CollectionInternals.getDisplay2(myVector) } - else if (x <= 0x100000) { N = 3; CollectionInternals.getDisplay3(myVector) } - else if (x <= 0x2000000) { N = 4; CollectionInternals.getDisplay4(myVector) } - else /*x <= 0x40000000*/{ N = 5; CollectionInternals.getDisplay5(myVector) } - while (N > 2) { - dataN = dataN((iX >>> (5*N))&0x1F).asInstanceOf[Array[AnyRef]] - N -= 1 - } - index1 = (iX >>> 5) & 0x1F - data1 = dataN((iX >>> 10) & 0x1F).asInstanceOf[Array[AnyRef]] - index = iX & 0x1F - data = data1(index1).asInstanceOf[Array[AnyRef]] - } - } - protected final def initVpTo(iX: Int): Unit = { - // WARNING--this is an exact copy of initTo! If you change one you must change the other! - // (Manually specialized this way for speed.) - myVectorLength match { - case x if x <= 0x20 => - index = iX - data = CollectionInternals.getDisplay0(myVectorIterator) - case x if x <= 0x400 => - index1 = iX >>> 5 - data1 = CollectionInternals.getDisplay1(myVectorIterator) - index = iX & 0x1F - data = data1(index1).asInstanceOf[Array[AnyRef]] - case x => - var N = 0 - var dataN: Array[AnyRef] = - if (x <= 0x8000) { N = 2; CollectionInternals.getDisplay2(myVectorIterator) } - else if (x <= 0x100000) { N = 3; CollectionInternals.getDisplay3(myVectorIterator) } - else if (x <= 0x2000000) { N = 4; CollectionInternals.getDisplay4(myVectorIterator) } - else /*x <= 0x40000000*/{ N = 5; CollectionInternals.getDisplay5(myVectorIterator) } - while (N > 2) { - dataN = dataN((iX >>> (5*N))&0x1F).asInstanceOf[Array[AnyRef]] - N -= 1 - } - index1 = (iX >>> 5) & 0x1F - data1 = dataN((iX >>> 10) & 0x1F).asInstanceOf[Array[AnyRef]] - index = iX & 0x1F - data = data1(index1).asInstanceOf[Array[AnyRef]] - } - } -} - -private[java8] class StepsAnyVector[A](underlying: Vector[A], _i0: Int, _iN: Int) -extends StepsLikeIndexed[A, StepsAnyVector[A]](_i0, _iN) -with StepsVectorLike[A] { - protected val myVector = if (CollectionInternals.getDirt(underlying)) null else underlying - protected val myVectorIterator = if (myVector == null) underlying.iterator else null - protected val myVectorLength = underlying.length - def next() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[A] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsAnyVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } -} - -private[java8] class StepsDoubleVector(underlying: Vector[Double], _i0: Int, _iN: Int) -extends StepsDoubleLikeIndexed[StepsDoubleVector](_i0, _iN) -with StepsVectorLike[Double] { - protected val myVector = if (CollectionInternals.getDirt(underlying)) null else underlying - protected val myVectorIterator = if (myVector == null) underlying.iterator else null - protected val myVectorLength = underlying.length - def nextDouble() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[Double] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsDoubleVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } -} - -private[java8] class StepsIntVector(underlying: Vector[Int], _i0: Int, _iN: Int) -extends StepsIntLikeIndexed[StepsIntVector](_i0, _iN) -with StepsVectorLike[Int] { - protected val myVector = if (CollectionInternals.getDirt(underlying)) null else underlying - protected val myVectorIterator = if (myVector == null) underlying.iterator else null - protected val myVectorLength = underlying.length - def nextInt() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[Int] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsIntVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } -} - -private[java8] class StepsLongVector(underlying: Vector[Long], _i0: Int, _iN: Int) -extends StepsLongLikeIndexed[StepsLongVector](_i0, _iN) -with StepsVectorLike[Long] { - protected val myVector = if (CollectionInternals.getDirt(underlying)) null else underlying - protected val myVectorIterator = if (myVector == null) underlying.iterator else null - protected val myVectorLength = underlying.length - def nextLong() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[Long] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsLongVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } -} - -////////////////////////// -// Value class adapters // -////////////////////////// - -final class RichVectorCanStep[T](private val underlying: Vector[T]) extends AnyVal with MakesStepper[T, EfficientSubstep] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { - case StepperShape.IntValue => new StepsIntVector (underlying.asInstanceOf[Vector[Int]], 0, underlying.length) - case StepperShape.LongValue => new StepsLongVector (underlying.asInstanceOf[Vector[Long]], 0, underlying.length) - case StepperShape.DoubleValue => new StepsDoubleVector(underlying.asInstanceOf[Vector[Double]], 0, underlying.length) - case _ => ss.parUnbox(new StepsAnyVector[T](underlying, 0, underlying.length)) - }).asInstanceOf[S with EfficientSubstep] -} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala deleted file mode 100644 index 04505a9..0000000 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.compat.java8.converterImpl - -import scala.compat.java8.collectionImpl._ -import Stepper._ - -/** Abstracts all the generic operations of stepping over a collection with a fast tail operation. - * Because of how Java 8 streams subdivide their spliterators, we do this by chunking a bit at - * a time, generating a long chain of chunks. These won't necessarily all be the same size, - * but if there are enough hopefully it won't matter. - * - * Subclasses MUST decrement `maxN` when consuming elements, or this will not work! - */ -private[java8] abstract class AbstractStepsWithTail[CC >: Null, Sub >: Null, Semi <: Sub](final protected var underlying: CC, final protected var maxN: Long) { - private var nextChunkSize: Int = 0 - protected def myIsEmpty(cc: CC): Boolean - protected def myTailOf(cc: CC): CC - def prepareParallelOperation(): this.type = { - if (maxN >= Int.MaxValue && nextChunkSize == 0) { - // Need parallel context to know whether to run this or not! - var u = underlying - var i = 0 - while (i < 1024 && !myIsEmpty(u)) { u = myTailOf(u); i += 1 } - if (i < 1024) maxN = i - else nextChunkSize = 64 // Guaranteed at least 16 chunks - } - this - } - def semiclone(chunk: Int): Semi - def characteristics(): Int = if (maxN < Int.MaxValue) Ordered | Sized | SubSized else Ordered - def estimateSize(): Long = if (maxN < Int.MaxValue) maxN else Long.MaxValue - def hasNext(): Boolean = if (maxN < Int.MaxValue) maxN > 0 else if (myIsEmpty(underlying)) { maxN = 0; false } else true - def substep(): Sub = { - prepareParallelOperation() - maxN match { - case x if x < 2 => null - case x if x >= Int.MaxValue => - var u = underlying - var i = 0 - val n = (nextChunkSize & 0xFFFFFFFC) // Use bottom two bits to count up - while (i < n && !myIsEmpty(u)) { - u = myTailOf(u) - i += 1 - } - if (myIsEmpty(u)) { - maxN = i - substep() // Different branch now, recursion is an easy way to get it - } - else { - val sub = semiclone(n) - underlying = u - if ((nextChunkSize & 3) == 3) nextChunkSize = if (n < 0x40000000) 2*n else n else nextChunkSize += 1 - sub - } - case x => - var half = x.toInt >>> 1 - val sub = semiclone(half) - maxN -= half - while (half > 0) { underlying = myTailOf(underlying); half -= 1 } - sub - } - } -} - -/** Abstracts the operation of stepping over a generic indexable collection */ -private[java8] abstract class StepsWithTail[A, CC >: Null, STA >: Null <: StepsWithTail[A, CC, _]](_underlying: CC, _maxN: Long) - extends AbstractStepsWithTail[CC, AnyStepper[A], STA](_underlying, _maxN) - with AnyStepper[A] -{} - -/** Abstracts the operation of stepping over an indexable collection of Doubles */ -private[java8] abstract class StepsDoubleWithTail[CC >: Null, STD >: Null <: StepsDoubleWithTail[CC, _]](_underlying: CC, _maxN: Long) - extends AbstractStepsWithTail[CC, DoubleStepper, STD](_underlying, _maxN) - with DoubleStepper -{} - -/** Abstracts the operation of stepping over an indexable collection of Ints */ -private[java8] abstract class StepsIntWithTail[CC >: Null, STI >: Null <: StepsIntWithTail[CC, _]](_underlying: CC, _maxN: Long) - extends AbstractStepsWithTail[CC, IntStepper, STI](_underlying, _maxN) - with IntStepper -{} - -/** Abstracts the operation of stepping over an indexable collection of Longs */ -private[java8] abstract class StepsLongWithTail[CC >: Null, STL >: Null <: StepsLongWithTail[CC, _]](_underlying: CC, _maxN: Long) - extends AbstractStepsWithTail[CC, LongStepper, STL](_underlying, _maxN) - with LongStepper -{} diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index 31a6523..9d06fc8 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -14,7 +14,7 @@ package scala.concurrent.java8 // Located in this package to access private[concurrent] members -import scala.concurrent.{ Future, ExecutionContext } +import scala.concurrent.Future import java.util.concurrent._ import scala.concurrent.impl.Promise.DefaultPromise import scala.util.{ Try, Success, Failure } @@ -22,8 +22,6 @@ import java.util.function.{ BiConsumer, Function ⇒ JF, Consumer, BiFunction } // TODO: make this private[scala] when genjavadoc allows for that. object FuturesConvertersImpl { - def InternalCallbackExecutor = Future.InternalCallbackExecutor - class CF[T](val wrapped: Future[T]) extends CompletableFuture[T] with (Try[T] => Unit) { override def apply(t: Try[T]): Unit = t match { case Success(v) ⇒ complete(v) diff --git a/src/test/java/scala/compat/java8/BoxingTest.java b/src/test/java/scala/compat/java8/BoxingTest.java index e0a2c03..7f798ff 100644 --- a/src/test/java/scala/compat/java8/BoxingTest.java +++ b/src/test/java/scala/compat/java8/BoxingTest.java @@ -18,24 +18,26 @@ public class BoxingTest { @Test public void nullBoxesInterpretedAsZeroF1() { - scala.Function1 jFunction1 = new JFunction1$mcII$sp() { + Object o = new JFunction1$mcII$sp() { @Override public int apply$mcII$sp(int v1) { return v1 + 1; } }; + scala.Function1 jFunction1 = (scala.Function1)o; Integer result = (Integer) jFunction1.apply(null); assert (result.intValue() == 1); } @Test public void nullBoxesInterpretedAsZeroF2() { - scala.Function2 jFunction2 = new JFunction2$mcIII$sp() { + Object o = new JFunction2$mcIII$sp() { @Override public int apply$mcIII$sp(int v1, int v2) { return v1 + v2 + 1; } }; + scala.Function2 jFunction2 = (scala.Function2)o; Integer result = (Integer) jFunction2.apply(null, null); assert (result.intValue() == 1); } diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index d3e118c..667e13c 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -16,26 +16,13 @@ import org.junit.Test import org.junit.Assert._ class StepConvertersTest { - import java.util._ import collectionImpl._ import converterImpl._ import StreamConverters._ // Includes StepConverters! import scala.{ collection => co } import collection.{ mutable => cm, immutable => ci, concurrent => cc } - def isAcc[X](x: X): Boolean = x match { - case _: AccumulatorStepper[_] => true - case _: DoubleAccumulatorStepper => true - case _: IntAccumulatorStepper => true - case _: LongAccumulatorStepper => true - case _ => false - } - - def isLin[X](x: X): Boolean = x match { - case _: AbstractStepsLikeIterator[_, _, _] => true - case _: AbstractStepsWithTail[_, _, _] => true - case _ => false - } + def isAcc[X](x: X): Boolean = x.getClass.getSimpleName.contains("AccumulatorStepper") trait SpecCheck { def check[X](x: X): Boolean @@ -65,7 +52,6 @@ class StepConvertersTest { assertTrue(x.isInstanceOf[Stepper[_]]) correctSpec.assert(x) assertTrue(!isAcc(x)) - assertTrue(isLin(x)) } def Fine[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { @@ -78,7 +64,6 @@ class StepConvertersTest { assertTrue(x.isInstanceOf[Stepper[_]]) correctSpec.assert(x) assertTrue(!isAcc(x)) - assertTrue(!isLin(x)) } def Tell[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { @@ -108,18 +93,15 @@ class StepConvertersTest { Okay( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) Okay( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) Okay( co.SortedSet[String]("salmon").stepper ) - IFFY( co.Traversable[String]("salmon").accumulate.stepper ) - IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).accumulate.stepper ) - IFFY( co.Traversable[String]("salmon").view.accumulate.stepper ) + IFFY( co.Iterable[String]("salmon").accumulate.stepper ) + IFFY( (co.Iterator[String]("salmon"): co.IterableOnce[String]).accumulate.stepper ) + IFFY( co.Iterable[String]("salmon").view.accumulate.stepper ) // Immutable section Okay( ci.::("salmon", Nil).stepper ) Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) - good( ci.HashMap[String, String]("fish" -> "salmon").stepper ) - good( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) - good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) good( ci.HashSet[String]("salmon").stepper ) good( ci.IndexedSeq[String]("salmon").stepper ) Okay( ci.IntMap[String](123456 -> "salmon").stepper ) @@ -143,10 +125,11 @@ class StepConvertersTest { Okay( ci.SortedMap[String, String]("fish" -> "salmon").keyStepper ) Okay( ci.SortedMap[String, String]("fish" -> "salmon").valueStepper ) Okay( ci.SortedSet[String]("salmon").stepper ) - Okay( ci.Stack[String]("salmon").stepper ) Okay( ci.Stream[String]("salmon").stepper ) _eh_( ci.Stream[String]("salmon").view.stepper ) - IFFY( ci.Traversable[String]("salmon").accumulate.stepper ) + Okay( ci.LazyList[String]("salmon").stepper ) + _eh_( ci.LazyList[String]("salmon").view.stepper ) + IFFY( ci.Iterable[String]("salmon").accumulate.stepper ) Okay( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) Okay( ci.TreeMap[String, String]("fish" -> "salmon").keyStepper ) Okay( ci.TreeMap[String, String]("fish" -> "salmon").valueStepper ) @@ -165,8 +148,7 @@ class StepConvertersTest { Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").keyStepper ) Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").valueStepper ) good( cm.ArrayBuffer[String]("salmon").stepper ) - good( ((Array("salmon"): cm.WrappedArray[String]): cm.ArrayLike[String, cm.WrappedArray[String]]).stepper ) - good( (Array("salmon"): cm.ArrayOps[String]).stepper ) + good( (Array("salmon"): cm.ArraySeq[String]).stepper ) good( cm.ArraySeq[String]("salmon").stepper ) _eh_( cm.ArrayStack[String]("salmon").stepper ) Okay( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) @@ -177,7 +159,6 @@ class StepConvertersTest { good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) Okay( cm.Iterable[String]("salmon").stepper ) - Okay( cm.LinearSeq[String]("salmon").stepper ) good( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) good( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) good( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) @@ -191,24 +172,21 @@ class StepConvertersTest { Okay( cm.Map[String, String]("fish" -> "salmon").stepper ) Okay( cm.Map[String, String]("fish" -> "salmon").keyStepper ) Okay( cm.Map[String, String]("fish" -> "salmon").valueStepper ) - Okay( cm.MutableList[String]("salmon").stepper ) Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").keyStepper ) Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").valueStepper ) Okay( cm.PriorityQueue[String]("salmon").stepper ) - Okay( cm.Queue[String]("salmon").stepper ) - good( cm.ResizableArray[String]("salmon").stepper ) + Fine( cm.Queue[String]("salmon").stepper ) // Used to be `Good` in 2.12, in 2.13 `Queue` is no longer a `LinearSeq` Okay( cm.Seq[String]("salmon").stepper ) Okay( cm.Set[String]("salmon").stepper ) Okay( cm.SortedSet[String]("salmon").stepper ) - Okay( cm.Stack[String]("salmon").stepper ) - IFFY( cm.Traversable[String]("salmon").accumulate.stepper ) + Fine( cm.Stack[String]("salmon").stepper ) // Used to be `Good` in 2.12, in 2.13 `Stack` is no longer a `LinearSeq` + IFFY( cm.Iterable[String]("salmon").accumulate.stepper ) Okay( cm.TreeSet[String]("salmon").stepper ) Okay( cm.UnrolledBuffer[String]("salmon").stepper ) Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").keyStepper ) Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").valueStepper ) - good( (Array("salmon"): cm.WrappedArray[String]).stepper ) // Java 6 converters section @@ -241,16 +219,14 @@ class StepConvertersTest { Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) Okay( co.SortedSet[Double](3.14159).stepper ) - IFFY( co.Traversable[Double](3.14159).accumulate.stepper ) - IFFY( (co.Iterator[Double](3.14159): co.TraversableOnce[Double]).accumulate.stepper ) - IFFY( co.Traversable[Double](3.14159).view.accumulate.stepper ) + IFFY( co.Iterable[Double](3.14159).accumulate.stepper ) + IFFY( (co.Iterator[Double](3.14159): co.IterableOnce[Double]).accumulate.stepper ) + IFFY( co.Iterable[Double](3.14159).view.accumulate.stepper ) // Immutable section Okay( ci.::(3.14159, Nil).stepper ) Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) - good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( ci.HashSet[Double](3.14159).stepper ) good( ci.IndexedSeq[Double](3.14159).stepper ) Okay( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) @@ -269,10 +245,11 @@ class StepConvertersTest { Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) Okay( ci.SortedSet[Double](3.14159).stepper ) - Okay( ci.Stack[Double](3.14159).stepper ) Okay( ci.Stream[Double](3.14159).stepper ) _eh_( ci.Stream[Double](3.14159).view.stepper ) - IFFY( ci.Traversable[Double](3.14159).accumulate.stepper ) + Okay( ci.LazyList[Double](3.14159).stepper ) + _eh_( ci.LazyList[Double](3.14159).view.stepper ) + IFFY( ci.Iterable[Double](3.14159).accumulate.stepper ) Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) Okay( ci.TreeSet[Double](3.14159).stepper ) @@ -287,8 +264,7 @@ class StepConvertersTest { Okay( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) Okay( cm.AnyRefMap[String,Double]("fish" -> 3.14159).valueStepper ) good( cm.ArrayBuffer[Double](3.14159).stepper ) - good( ((Array(3.14159): cm.WrappedArray[Double]): cm.ArrayLike[Double, cm.WrappedArray[Double]]).stepper ) - good( (Array(3.14159): cm.ArrayOps[Double]).stepper ) + good( (Array(3.14159): cm.ArraySeq[Double]).stepper ) good( cm.ArraySeq[Double](3.14159).stepper ) _eh_( cm.ArrayStack[Double](3.14159).stepper ) Okay( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) @@ -298,7 +274,6 @@ class StepConvertersTest { good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) Okay( cm.Iterable[Double](3.14159).stepper ) - Okay( cm.LinearSeq[Double](3.14159).stepper ) good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) Okay( cm.LinkedHashSet[Double](3.14159).stepper ) @@ -308,22 +283,19 @@ class StepConvertersTest { Okay( cm.LongMap[Double](9876543210L -> 3.14159).valueStepper ) Okay( cm.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( cm.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) - Okay( cm.MutableList[Double](3.14159).stepper ) Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) Okay( cm.PriorityQueue[Double](3.14159).stepper ) - Okay( cm.Queue[Double](3.14159).stepper ) - good( cm.ResizableArray[Double](3.14159).stepper ) + Fine( cm.Queue[Double](3.14159).stepper ) // Used to be `Good` in 2.12, in 2.13 `Queue` is no longer a `LinearSeq` Okay( cm.Seq[Double](3.14159).stepper ) Okay( cm.Set[Double](3.14159).stepper ) Okay( cm.SortedSet[Double](3.14159).stepper ) - Okay( cm.Stack[Double](3.14159).stepper ) - IFFY( cm.Traversable[Double](3.14159).accumulate.stepper ) + Fine( cm.Stack[Double](3.14159).stepper ) // Used to be `Good` in 2.12, in 2.13 `Stack` is no longer a `LinearSeq` + IFFY( cm.Iterable[Double](3.14159).accumulate.stepper ) Okay( cm.TreeSet[Double](3.14159).stepper ) Okay( cm.UnrolledBuffer[Double](3.14159).stepper ) Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - good( (Array(3.14159): cm.WrappedArray[Double]).stepper ) // Java 6 converters section @@ -363,16 +335,14 @@ class StepConvertersTest { Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) Okay( co.SortedSet[Int](654321).stepper ) - IFFY( co.Traversable[Int](654321).accumulate.stepper ) - IFFY( (co.Iterator[Int](654321): co.TraversableOnce[Int]).accumulate.stepper ) - IFFY( co.Traversable[Int](654321).view.accumulate.stepper ) + IFFY( co.Iterable[Int](654321).accumulate.stepper ) + IFFY( (co.Iterator[Int](654321): co.IterableOnce[Int]).accumulate.stepper ) + IFFY( co.Iterable[Int](654321).view.accumulate.stepper ) // Immutable section Okay( ci.::(654321, Nil).stepper ) Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) - good( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( ci.HashSet[Int](654321).stepper ) good( ci.IndexedSeq[Int](654321).stepper ) Okay( ci.IntMap[Int](123456 -> 654321).keyStepper ) @@ -392,10 +362,11 @@ class StepConvertersTest { Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) Okay( ci.SortedSet[Int](654321).stepper ) - Okay( ci.Stack[Int](654321).stepper ) Okay( ci.Stream[Int](654321).stepper ) _eh_( ci.Stream[Int](654321).view.stepper ) - IFFY( ci.Traversable[Int](654321).accumulate.stepper ) + Okay( ci.LazyList[Int](654321).stepper ) + _eh_( ci.LazyList[Int](654321).view.stepper ) + IFFY( ci.Iterable[Int](654321).accumulate.stepper ) Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).valueStepper ) Okay( ci.TreeSet[Int](654321).stepper ) @@ -410,8 +381,7 @@ class StepConvertersTest { Okay( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) Okay( cm.AnyRefMap[String, Int]("fish" -> 654321).valueStepper ) good( cm.ArrayBuffer[Int](654321).stepper ) - good( ((Array(654321): cm.WrappedArray[Int]): cm.ArrayLike[Int, cm.WrappedArray[Int]]).stepper ) - good( (Array(654321): cm.ArrayOps[Int]).stepper ) + good( (Array(654321): cm.ArraySeq[Int]).stepper ) good( cm.ArraySeq[Int](654321).stepper ) _eh_( cm.ArrayStack[Int](654321).stepper ) Okay( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) @@ -421,7 +391,6 @@ class StepConvertersTest { good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) Okay( cm.Iterable[Int](654321).stepper ) - Okay( cm.LinearSeq[Int](654321).stepper ) good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) Okay( cm.LinkedHashSet[Int](654321).stepper ) @@ -431,22 +400,19 @@ class StepConvertersTest { Okay( cm.LongMap[Int](9876543210L -> 654321).valueStepper ) Okay( cm.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( cm.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) - Okay( cm.MutableList[Int](654321).stepper ) Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) Okay( cm.PriorityQueue[Int](654321).stepper ) - Okay( cm.Queue[Int](654321).stepper ) - good( cm.ResizableArray[Int](654321).stepper ) + Fine( cm.Queue[Int](654321).stepper ) // Used to be `Good` in 2.12, in 2.13 `Queue` is no longer a `LinearSeq` Okay( cm.Seq[Int](654321).stepper ) Okay( cm.Set[Int](654321).stepper ) Okay( cm.SortedSet[Int](654321).stepper ) - Okay( cm.Stack[Int](654321).stepper ) - IFFY( cm.Traversable[Int](654321).accumulate.stepper ) + Fine( cm.Stack[Int](654321).stepper ) // Used to be `Good` in 2.12, in 2.13 `Stack` is no longer a `LinearSeq` + IFFY( cm.Iterable[Int](654321).accumulate.stepper ) Okay( cm.TreeSet[Int](654321).stepper ) Okay( cm.UnrolledBuffer[Int](654321).stepper ) Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - good( (Array(654321): cm.WrappedArray[Int]).stepper ) // Java 6 converters section @@ -462,12 +428,12 @@ class StepConvertersTest { implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") good( Array[Short](654321.toShort).stepper ) - good( (Array[Short](654321.toShort): cm.WrappedArray[Short]).stepper ) + good( (Array[Short](654321.toShort): cm.ArraySeq[Short]).stepper ) //TODO: None of these currently work because there are no native Stepper implementations: //good( ci.NumericRange(123456.toShort, 123458.toShort, 1.toShort).stepper ) - //good( ((Array[Short](654321.toShort): cm.WrappedArray[Short]): cm.ArrayLike[Short, cm.WrappedArray[Short]]).stepper ) + //good( ((Array[Short](654321.toShort): cm.ArraySeq[Short]): cm.ArrayLike[Short, cm.ArraySeq[Short]]).stepper ) //good( (Array[Short](654321.toShort): cm.ArrayOps[Short]).stepper ) //good( cm.ResizableArray[Short](654321.toShort).stepper ) } @@ -500,16 +466,14 @@ class StepConvertersTest { Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) Okay( co.SortedSet[Long](0x123456789L).stepper ) - IFFY( co.Traversable[Long](0x123456789L).accumulate.stepper ) - IFFY( (co.Iterator[Long](0x123456789L): co.TraversableOnce[Long]).accumulate.stepper ) - IFFY( co.Traversable[Long](0x123456789L).view.accumulate.stepper ) + IFFY( co.Iterable[Long](0x123456789L).accumulate.stepper ) + IFFY( (co.Iterator[Long](0x123456789L): co.IterableOnce[Long]).accumulate.stepper ) + IFFY( co.Iterable[Long](0x123456789L).view.accumulate.stepper ) // Immutable section Okay( ci.::(0x123456789L, Nil).stepper ) Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) - good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( ci.HashSet[Long](0x123456789L).stepper ) good( ci.IndexedSeq[Long](0x123456789L).stepper ) Okay( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) @@ -529,10 +493,11 @@ class StepConvertersTest { Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) Okay( ci.SortedSet[Long](0x123456789L).stepper ) - Okay( ci.Stack[Long](0x123456789L).stepper ) Okay( ci.Stream[Long](0x123456789L).stepper ) _eh_( ci.Stream[Long](0x123456789L).view.stepper ) - IFFY( ci.Traversable[Long](0x123456789L).accumulate.stepper ) + Okay( ci.LazyList[Long](0x123456789L).stepper ) + _eh_( ci.LazyList[Long](0x123456789L).view.stepper ) + IFFY( ci.Iterable[Long](0x123456789L).accumulate.stepper ) Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) Okay( ci.TreeSet[Long](0x123456789L).stepper ) @@ -547,8 +512,7 @@ class StepConvertersTest { Okay( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) Okay( cm.AnyRefMap[String,Long]("fish" -> 0x123456789L).valueStepper ) good( cm.ArrayBuffer[Long](0x123456789L).stepper ) - good( ((Array(0x123456789L): cm.WrappedArray[Long]): cm.ArrayLike[Long, cm.WrappedArray[Long]]).stepper ) - good( (Array(0x123456789L): cm.ArrayOps[Long]).stepper ) + good( (Array(0x123456789L): cm.ArraySeq[Long]).stepper ) good( cm.ArraySeq[Long](0x123456789L).stepper ) _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) Okay( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) @@ -558,7 +522,6 @@ class StepConvertersTest { good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) Okay( cm.Iterable[Long](0x123456789L).stepper ) - Okay( cm.LinearSeq[Long](0x123456789L).stepper ) good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) Okay( cm.LinkedHashSet[Long](0x123456789L).stepper ) @@ -569,22 +532,19 @@ class StepConvertersTest { Okay( cm.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) Okay( cm.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( cm.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - Okay( cm.MutableList[Long](0x123456789L).stepper ) Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) Okay( cm.PriorityQueue[Long](0x123456789L).stepper ) - Okay( cm.Queue[Long](0x123456789L).stepper ) - good( cm.ResizableArray[Long](0x123456789L).stepper ) + Fine( cm.Queue[Long](0x123456789L).stepper ) // Used to be `Good` in 2.12, in 2.13 `Queue` is no longer a `LinearSeq` Okay( cm.Seq[Long](0x123456789L).stepper ) Okay( cm.Set[Long](0x123456789L).stepper ) Okay( cm.SortedSet[Long](0x123456789L).stepper ) - Okay( cm.Stack[Long](0x123456789L).stepper ) - IFFY( cm.Traversable[Long](0x123456789L).accumulate.stepper ) + Fine( cm.Stack[Long](0x123456789L).stepper ) // Used to be `Good` in 2.12, in 2.13 `Stack` is no longer a `LinearSeq` + IFFY( cm.Iterable[Long](0x123456789L).accumulate.stepper ) Okay( cm.TreeSet[Long](0x123456789L).stepper ) Okay( cm.UnrolledBuffer[Long](0x123456789L).stepper ) Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - good( (Array(0x123456789L): cm.WrappedArray[Long]).stepper ) // Java 6 converters section @@ -600,7 +560,6 @@ class StepConvertersTest { implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) - good( ("salmon": ci.StringOps).stepper ) good( ("salmon": ci.WrappedString).stepper ) } } diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 7bbbcd9..77b0109 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -12,22 +12,25 @@ package scala.compat.java8 +import java.util + import org.junit.Test import org.junit.Assert._ - import java.util.Spliterator import collectionImpl._ +import StreamConverters._ +import scala.collection.{AnyStepper, IntStepper} -class IncStepperA(private val size0: Long) extends NextStepper[Int] { +class IncStepperA(private val size0: Long) extends IntStepper { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L - def characteristics = Stepper.Sized | Stepper.SubSized | Stepper.Ordered - def knownSize = math.max(0L, size0 - i) + def characteristics = Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED + override def estimateSize: Long = math.max(0L, size0 - i) def hasStep = i < size0 def nextStep() = { i += 1; (i - 1).toInt } - def substep() = if (knownSize <= 1) null else { + def trySplit() = if (estimateSize <= 1) null else { val sub = new IncStepperA(size0 - (size0 - i)/2) sub.i = i i = sub.size0 @@ -35,25 +38,10 @@ class IncStepperA(private val size0: Long) extends NextStepper[Int] { } } -class IncStepperB(private val size0: Long) extends TryStepper[Int] { - if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") - protected var myCache: Int = 0 - private var i = 0L - def characteristics = Stepper.Sized | Stepper.SubSized | Stepper.Ordered - def knownUncachedSize = math.max(0L, size0 - i) - protected def tryUncached(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } - def substep() = if (knownSize <= 1) null else { - val sub = new IncStepperB(size0 - (size0 - i)/2) - sub.i = i - i = sub.size0 - sub - } -} - class IncSpliterator(private val size0: Long) extends Spliterator.OfInt { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L - def characteristics() = Stepper.Sized | Stepper.SubSized | Stepper.Ordered + def characteristics = Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED def estimateSize() = math.max(0L, size0 - i) def tryAdvance(f: java.util.function.IntConsumer): Boolean = if (i >= size0) false else { f.accept(i.toInt); i += 1; true } def trySplit(): Spliterator.OfInt = if (i+1 >= size0) null else { @@ -67,17 +55,26 @@ class IncSpliterator(private val size0: Long) extends Spliterator.OfInt { class MappingStepper[@specialized (Double, Int, Long) A, @specialized(Double, Int, Long) B](underlying: Stepper[A], mapping: A => B) extends Stepper[B] { def characteristics = underlying.characteristics - def knownSize = underlying.knownSize def hasStep = underlying.hasStep def nextStep() = mapping(underlying.nextStep()) - def tryStep(f: B => Unit): Boolean = underlying.tryStep(a => f(mapping(a))) - override def foreach(f: B => Unit): Unit = { underlying.foreach(a => f(mapping(a))) } + + override def trySplit(): Stepper[B] = { + val r = underlying.trySplit() + if (r == null) null else new MappingStepper[A, B](r, mapping) + } + + override def estimateSize: Long = underlying.estimateSize + + override def javaIterator[_ >: B]: util.Iterator[_] = new util.Iterator[B] { + override def hasNext: Boolean = underlying.hasStep + override def next(): B = mapping(underlying.nextStep()) + } def substep() = { val undersub = underlying.substep() if (undersub == null) null else new MappingStepper(undersub, mapping) } - def spliterator: Spliterator[B] = new MappingSpliterator[A, B](underlying.spliterator, mapping) + def spliterator[_ >: B]: Spliterator[_] = new MappingSpliterator[A, B](underlying.spliterator.asInstanceOf[Spliterator[A]], mapping) } class MappingSpliterator[A, B](private val underlying: Spliterator[A], mapping: A => B) extends Spliterator[B] { @@ -121,6 +118,26 @@ class IntToLongSpliterator(private val underlying: Spliterator.OfInt, mapping: I } } +class SpliteratorStepper[A](sp: Spliterator[A]) extends AnyStepper[A] { + override def trySplit(): AnyStepper[A] = { + val r = sp.trySplit() + if (r == null) null else new SpliteratorStepper(r) + } + + var cache: AnyRef = null + + override def hasStep: Boolean = cache != null || sp.tryAdvance(x => cache = x.asInstanceOf[AnyRef]) + + override def nextStep(): A = if (hasStep) { + val r = cache + cache = null + r.asInstanceOf[A] + } else throw new NoSuchElementException("") + + override def estimateSize: Long = sp.estimateSize() + + override def characteristics: Int = sp.characteristics() +} class StepperTest { def subs[Z, A, CC <: Stepper[A]](zero: Z)(s: Stepper[A])(f: Stepper[A] => Z, op: (Z, Z) => Z): Z = { @@ -133,36 +150,25 @@ class StepperTest { } val sizes = Vector(0, 1, 2, 4, 15, 17, 2512) - def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap{ i => + def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap{ i => Vector( i -> new IncStepperA(i), - i -> new IncStepperB(i), - i -> Stepper.ofSpliterator(new IncSpliterator(i)), + i -> new SpliteratorStepper(new IncSpliterator(i).asInstanceOf[Spliterator[Int]]), i -> new MappingStepper[Int,Int](new IncStepperA(i), x => x), - i -> new MappingStepper[Long, Int](Stepper.ofSpliterator(new IntToLongSpliterator(new IncSpliterator(i), _.toLong)), _.toInt), - i -> new MappingStepper[Double, Int](Stepper.ofSpliterator(new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble)), _.toInt), - i -> new MappingStepper[String, Int](Stepper.ofSpliterator(new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)), _.toInt) - ) ++ - { - // Implicitly converted instead of explicitly - import SpliteratorConverters._ - Vector[(Int, Stepper[Int])]( - i -> (new IncSpliterator(i)).stepper, - i -> new MappingStepper[Long, Int]((new IntToLongSpliterator(new IncSpliterator(i), _.toLong)).stepper, _.toInt), - i -> new MappingStepper[Double, Int]((new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble)).stepper, _.toInt), - i -> new MappingStepper[String, Int]((new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)).stepper, _.toInt) - ) - } + i -> new MappingStepper[Long, Int](new SpliteratorStepper(new IntToLongSpliterator(new IncSpliterator(i), _.toLong).asInstanceOf[Spliterator[Long]]), _.toInt), + i -> new MappingStepper[Double, Int](new SpliteratorStepper(new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble).asInstanceOf[Spliterator[Double]]), _.toInt), + i -> new MappingStepper[String, Int](new SpliteratorStepper(new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)), _.toInt) + ) } @Test def stepping(): Unit = { - sources.foreach{ case (i, s) => assert((0 until i).forall{ j => s.hasStep && s.nextStep == j } && !s.hasStep) } + sources.foreach{ case (i, s) => assert((0 until i).forall{ j => s.hasStep && s.nextStep() == j } && !s.hasStep) } sources.foreach{ case (i, s) => val set = collection.mutable.BitSet.empty subs(0)(s)( { x => - while (x.hasStep) { val y = x.nextStep; assert(!(set contains y)); set += y } + while (x.hasStep) { val y = x.nextStep(); assert(!(set contains y)); set += y } 0 }, _ + _ @@ -175,14 +181,14 @@ class StepperTest { def trying(): Unit = { sources.foreach{ case (i,s) => val set = collection.mutable.BitSet.empty - while (s.tryStep{ y => assert(!(set contains y)); set += y }) {} + while (s.hasStep) { val y = s.nextStep(); assert(!(set contains y)); set += y } assert((0 until i).toSet == set) } sources.foreach{ case (i,s) => val set = collection.mutable.BitSet.empty subs(0)(s)( { x => - while(x.tryStep{ y => assert(!(set contains y)); set += y }) {} + while (x.hasStep) { val y = x.nextStep(); assert(!(set contains y)); set += y } 0 }, _ + _ @@ -194,36 +200,30 @@ class StepperTest { @Test def substepping(): Unit = { sources.foreach{ case (i,s) => - val ss = s.substep + val ss = s.substep() assertEquals(ss == null, i < 2) if (ss != null) { assertTrue(s.hasStep) assertTrue(ss.hasStep) - val c1 = s.count - val c2 = ss.count + val c1 = s.count() + val c2 = ss.count() assertEquals(s"$i != $c1 + $c2 from ${s.getClass.getName}", i, c1 + c2) } - else assertEquals(i, s.count) + else assertEquals(i, s.count()) } } @Test def characteristically(): Unit = { - val expected = Stepper.Sized | Stepper.SubSized | Stepper.Ordered + val expected = Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED sources.foreach{ case (_,s) => assertEquals(s.characteristics, expected)} sources.foreach{ case (_,s) => subs(0)(s)(x => { assertEquals(x.characteristics, expected); 0 }, _ + _) } } - @Test - def knownSizes(): Unit = { - sources.foreach{ case (i,s) => assertEquals(i.toLong, s.knownSize) } - sources.foreach{ case (i,s) => if (i > 0) subs(0)(s)(x => { assertEquals(x.knownSize, 1L); 0 }, _ + _) } - } - @Test def count_only(): Unit = { - sources.foreach{ case (i, s) => assertEquals(i, s.count) } - sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s)(_.count.toInt, _ + _)) } + sources.foreach{ case (i, s) => assertEquals(i, s.count()) } + sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s)(_.count().toInt, _ + _)) } } @Test @@ -244,7 +244,7 @@ class StepperTest { def finding(): Unit = { for (k <- 0 until 100) { (sources zip sources).foreach{ case ((i,s), (j,t)) => - val x = util.Random.nextInt(math.min(i,j)+3) + val x = scala.util.Random.nextInt(math.min(i,j)+3) val a = s.find(_ == x) val b = subs(None: Option[Int])(t)(_.find(_ == x), _ orElse _) assertEquals(a, b) @@ -267,7 +267,7 @@ class StepperTest { sources.foreach{ case (i,s) => assertEquals(expected(i), s.foldTo(0)(_ + _)(_ >= 6*i)) } sources.foreach{ case (_,s) => assertEquals(-1, s.foldTo(-1)(_ * _)(_ => true)) } sources.foreach{ case (i,s) => - val ss = s.substep + val ss = s.substep() val x = s.foldTo( if (ss == null) 0 else ss.foldTo(0)(_ + _)(_ >= 6*i) )(_ + _)(_ >= 6*i) assertEquals(expected(i), x) } @@ -307,11 +307,11 @@ class StepperTest { def spliterating(): Unit = { sources.foreach{ case (i,s) => var sum = 0 - s.spliterator.forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int): Unit = { sum += i } }) + s.spliterator.asInstanceOf[Spliterator[Int]].forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int): Unit = { sum += i } }) assertEquals(sum, (0 until i).sum) } sources.foreach{ case (i,s) => - val sum = subs(0)(s)(x => { var sm = 0; x.spliterator.forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int): Unit = { sm += i } }); sm }, _ + _) + val sum = subs(0)(s)(x => { var sm = 0; x.spliterator.asInstanceOf[Spliterator[Int]].forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int): Unit = { sm += i } }); sm }, _ + _) assertEquals(sum, (0 until i).sum) } } diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index e0baef7..f2a084f 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -19,8 +19,6 @@ import org.junit.Assert._ import java.util.stream._ import StreamConverters._ -import scala.compat.java8.collectionImpl.IntStepper -import scala.compat.java8.converterImpl.MakesStepper class StreamConvertersTest { @@ -46,8 +44,8 @@ class StreamConvertersTest { for (n <- ns) { val vecO = arrayO(n).toVector val accO = newStream(n).parallel.accumulate - assertEq(vecO, newStream(n).accumulate.to[Vector], s"stream $n to vector") - assertEq(vecO, accO.to[Vector], s"stream $n to vector in parallel") + assertEq(vecO, newStream(n).accumulate.to(Vector), s"stream $n to vector") + assertEq(vecO, accO.to(Vector), s"stream $n to vector in parallel") assertEq(vecO, accO.toArray.toVector, s"stream $n to vector via array in parallel") assertEq(vecO, accO.iterator.toVector, s"stream $n to vector via iterator in parallel") assertEq(vecO, accO.toList.toVector, s"stream $n to vector via list in parallel") @@ -60,8 +58,8 @@ class StreamConvertersTest { val accD = if (boxless) newDoubleStream(n).parallel.accumulate else newDoubleStream(n).boxed.parallel.accumulatePrimitive - assertEq(vecD, newDoubleStream(n).accumulate.to[Vector], s"double stream $n to vector $sbox") - assertEq(vecD, accD.to[Vector], s"double stream $n to vector in parallel $sbox") + assertEq(vecD, newDoubleStream(n).accumulate.to(Vector), s"double stream $n to vector $sbox") + assertEq(vecD, accD.to(Vector), s"double stream $n to vector in parallel $sbox") assertEq(vecD, accD.toArray.toVector, s"double stream $n to vector via array in parallel $sbox") assertEq(vecD, accD.iterator.toVector, s"double stream $n to vector via iterator in parallel $sbox") assertEq(vecD, accD.toList.toVector, s"double stream $n to vector via list in parallel $sbox") @@ -72,8 +70,8 @@ class StreamConvertersTest { val accI = if (boxless) newIntStream(n).parallel.accumulate else newIntStream(n).boxed.parallel.accumulatePrimitive - assertEq(vecI, newIntStream(n).accumulate.to[Vector], s"int stream $n to vector $sbox") - assertEq(vecI, accI.to[Vector], s"int stream $n to vector in parallel $sbox") + assertEq(vecI, newIntStream(n).accumulate.to(Vector), s"int stream $n to vector $sbox") + assertEq(vecI, accI.to(Vector), s"int stream $n to vector in parallel $sbox") assertEq(vecI, accI.toArray.toVector, s"int stream $n to vector via array in parallel $sbox") assertEq(vecI, accI.iterator.toVector, s"int stream $n to vector via iterator in parallel $sbox") assertEq(vecI, accI.toList.toVector, s"int stream $n to vector via list in parallel $sbox") @@ -84,8 +82,8 @@ class StreamConvertersTest { val accL = if (boxless) newLongStream(n).parallel.accumulate else newLongStream(n).boxed.parallel.accumulatePrimitive - assertEq(vecL, newLongStream(n).accumulate.to[Vector], s"long stream $n to vector $sbox") - assertEq(vecL, accL.to[Vector], s"long stream $n to vector in parallel $sbox") + assertEq(vecL, newLongStream(n).accumulate.to(Vector), s"long stream $n to vector $sbox") + assertEq(vecL, accL.to(Vector), s"long stream $n to vector in parallel $sbox") assertEq(vecL, accL.toArray.toVector, s"long stream $n to vector via array in parallel $sbox") assertEq(vecL, accL.iterator.toVector, s"long stream $n to vector via iterator in parallel $sbox") assertEq(vecL, accL.toList.toVector, s"long stream $n to vector via list in parallel $sbox") @@ -99,20 +97,20 @@ class StreamConvertersTest { def streamToScala(): Unit = { for (n <- ns) { val vecO = arrayO(n).toVector - assertEq(vecO, newStream(n).toScala[Vector]) - assertEq(vecO, newStream(n).parallel.toScala[Vector]) + assertEq(vecO, newStream(n).toScala(Vector)) + assertEq(vecO, newStream(n).parallel.toScala(Vector)) val vecD = arrayD(n).toVector - assertEq(vecD, newDoubleStream(n).toScala[Vector]) - assertEq(vecD, newDoubleStream(n).parallel.toScala[Vector]) + assertEq(vecD, newDoubleStream(n).toScala(Vector)) + assertEq(vecD, newDoubleStream(n).parallel.toScala(Vector)) val vecI = arrayI(n).toVector - assertEq(vecI, newIntStream(n).toScala[Vector]) - assertEq(vecI, newIntStream(n).parallel.toScala[Vector]) + assertEq(vecI, newIntStream(n).toScala(Vector)) + assertEq(vecI, newIntStream(n).parallel.toScala(Vector)) val vecL = arrayL(n).toVector - assertEq(vecL, newLongStream(n).toScala[Vector]) - assertEq(vecL, newLongStream(n).parallel.toScala[Vector]) + assertEq(vecL, newLongStream(n).toScala(Vector)) + assertEq(vecL, newLongStream(n).parallel.toScala(Vector)) } } @@ -123,15 +121,15 @@ class StreamConvertersTest { assert(newLongStream(1).boxed.unboxed.isInstanceOf[LongStream]) } - import collection.mutable.{ ArrayBuffer, WrappedArray } + import collection.mutable.{ ArrayBuffer, ArraySeq } def abufO(n: Int) = { val ab = new ArrayBuffer[String]; arrayO(n).foreach(ab += _); ab } def abufD(n: Int) = { val ab = new ArrayBuffer[Double]; arrayD(n).foreach(ab += _); ab } def abufI(n: Int) = { val ab = new ArrayBuffer[Int]; arrayI(n).foreach(ab += _); ab } def abufL(n: Int) = { val ab = new ArrayBuffer[Long]; arrayL(n).foreach(ab += _); ab } - def wrapO(n: Int): WrappedArray[String] = arrayO(n) - def wrapD(n: Int): WrappedArray[Double] = arrayD(n) - def wrapI(n: Int): WrappedArray[Int] = arrayI(n) - def wrapL(n: Int): WrappedArray[Long] = arrayL(n) + def wrapO(n: Int): ArraySeq[String] = arrayO(n) + def wrapD(n: Int): ArraySeq[Double] = arrayD(n) + def wrapI(n: Int): ArraySeq[Int] = arrayI(n) + def wrapL(n: Int): ArraySeq[Long] = arrayL(n) def vectO(n: Int) = arrayO(n).toVector def vectD(n: Int) = arrayD(n).toVector def vectI(n: Int) = arrayI(n).toVector @@ -152,18 +150,18 @@ class StreamConvertersTest { val vecO = vectO(n) val hsO = hsetO(n) // Seems like a lot of boilerplate, but we need it to test implicit resolution - assertEq(seqO, seqO.seqStream.toScala[Seq]) - assertEq(seqO, seqO.stepper.parStream.toScala[Seq]) // Must go through stepper if we're unsure whether we can parallelize well - assertEq(seqO, arrO.seqStream.toScala[Seq]) - assertEq(seqO, arrO.parStream.toScala[Seq]) - assertEq(seqO, abO.seqStream.toScala[Seq]) - assertEq(seqO, abO.parStream.toScala[Seq]) - assertEq(seqO, wrO.seqStream.toScala[Seq]) - assertEq(seqO, wrO.parStream.toScala[Seq]) - assertEq(seqO, vecO.seqStream.toScala[Seq]) - assertEq(seqO, vecO.parStream.toScala[Seq]) - assertEq(seqO, hsO.seqStream.toScala[Seq].sortBy(_.toInt)) - assertEq(seqO, hsO.parStream.toScala[Seq].sortBy(_.toInt)) + assertEq(seqO, seqO.seqStream.toScala(Seq)) +// assertEq(seqO, seqO.stepper.parStream.toScala(Seq) // Must go through stepper if we're unsure whether we can parallelize well + assertEq(seqO, arrO.seqStream.toScala(Seq)) + assertEq(seqO, arrO.parStream.toScala(Seq)) + assertEq(seqO, abO.seqStream.toScala(Seq)) + assertEq(seqO, abO.parStream.toScala(Seq)) + assertEq(seqO, wrO.seqStream.toScala(Seq)) + assertEq(seqO, wrO.parStream.toScala(Seq)) + assertEq(seqO, vecO.seqStream.toScala(Seq)) + assertEq(seqO, vecO.parStream.toScala(Seq)) +// assertEq(seqO, hsO.seqStream.toScala(Seq.sortBy(_.toInt)) +// assertEq(seqO, hsO.parStream.toScala(Seq.sortBy(_.toInt)) val arrD = arrayD(n) val seqD = arrD.toSeq @@ -171,28 +169,28 @@ class StreamConvertersTest { val wrD = wrapD(n) val vecD = vectD(n) val hsD = hsetD(n) - assertEq(seqD, seqD.seqStream.toScala[Seq]) - assertEq(seqD, seqD.stepper.parStream.toScala[Seq]) - assertEq(seqD, arrD.seqStream.toScala[Seq]) - assertEq(seqD, arrD.parStream.toScala[Seq]) + assertEq(seqD, seqD.seqStream.toScala(Seq)) +// assertEq(seqD, seqD.stepper.parStream.toScala(Seq) + assertEq(seqD, arrD.seqStream.toScala(Seq)) + assertEq(seqD, arrD.parStream.toScala(Seq)) assert(arrD.seqStream.isInstanceOf[DoubleStream]) assert(arrD.parStream.isInstanceOf[DoubleStream]) - assertEq(seqD, abD.seqStream.toScala[Seq]) - assertEq(seqD, abD.parStream.toScala[Seq]) + assertEq(seqD, abD.seqStream.toScala(Seq)) + assertEq(seqD, abD.parStream.toScala(Seq)) assert(abD.seqStream.isInstanceOf[DoubleStream]) assert(abD.parStream.isInstanceOf[DoubleStream]) - assertEq(seqD, wrD.seqStream.toScala[Seq]) - assertEq(seqD, wrD.parStream.toScala[Seq]) + assertEq(seqD, wrD.seqStream.toScala(Seq)) + assertEq(seqD, wrD.parStream.toScala(Seq)) assert(wrD.seqStream.isInstanceOf[DoubleStream]) assert(wrD.parStream.isInstanceOf[DoubleStream]) - assertEq(seqD, vecD.seqStream.toScala[Seq]) - assertEq(seqD, vecD.parStream.toScala[Seq]) + assertEq(seqD, vecD.seqStream.toScala(Seq)) + assertEq(seqD, vecD.parStream.toScala(Seq)) assert(vecD.seqStream.isInstanceOf[DoubleStream]) assert(vecD.parStream.isInstanceOf[DoubleStream]) - assertEq(seqD, hsD.seqStream.toScala[Seq].sorted) - assertEq(seqD, hsD.parStream.toScala[Seq].sorted) - assert(hsD.seqStream.isInstanceOf[DoubleStream]) - assert(hsD.parStream.isInstanceOf[DoubleStream]) +// assertEq(seqD, hsD.seqStream.toScala(Seq.sorted) +// assertEq(seqD, hsD.parStream.toScala(Seq.sorted) +// assert(hsD.seqStream.isInstanceOf[DoubleStream]) +// assert(hsD.parStream.isInstanceOf[DoubleStream]) val arrI = arrayI(n) val seqI = arrI.toSeq @@ -200,28 +198,28 @@ class StreamConvertersTest { val wrI = wrapI(n) val vecI = vectI(n) val hsI = hsetI(n) - assertEq(seqI, seqI.seqStream.toScala[Seq]) - assertEq(seqI, seqI.stepper.parStream.toScala[Seq]) - assertEq(seqI, arrI.seqStream.toScala[Seq]) - assertEq(seqI, arrI.parStream.toScala[Seq]) + assertEq(seqI, seqI.seqStream.toScala(Seq)) +// assertEq(seqI, seqI.stepper.parStream.toScala(Seq) + assertEq(seqI, arrI.seqStream.toScala(Seq)) + assertEq(seqI, arrI.parStream.toScala(Seq)) assert(arrI.seqStream.isInstanceOf[IntStream]) assert(arrI.parStream.isInstanceOf[IntStream]) - assertEq(seqI, abI.seqStream.toScala[Seq]) - assertEq(seqI, abI.parStream.toScala[Seq]) + assertEq(seqI, abI.seqStream.toScala(Seq)) + assertEq(seqI, abI.parStream.toScala(Seq)) assert(abI.seqStream.isInstanceOf[IntStream]) assert(abI.parStream.isInstanceOf[IntStream]) - assertEq(seqI, wrI.seqStream.toScala[Seq]) - assertEq(seqI, wrI.parStream.toScala[Seq]) + assertEq(seqI, wrI.seqStream.toScala(Seq)) + assertEq(seqI, wrI.parStream.toScala(Seq)) assert(wrI.seqStream.isInstanceOf[IntStream]) assert(wrI.parStream.isInstanceOf[IntStream]) - assertEq(seqI, vecI.seqStream.toScala[Seq]) - assertEq(seqI, vecI.parStream.toScala[Seq]) + assertEq(seqI, vecI.seqStream.toScala(Seq)) + assertEq(seqI, vecI.parStream.toScala(Seq)) assert(vecI.seqStream.isInstanceOf[IntStream]) assert(vecI.parStream.isInstanceOf[IntStream]) - assertEq(seqI, hsI.seqStream.toScala[Seq].sorted) - assertEq(seqI, hsI.parStream.toScala[Seq].sorted) - assert(hsI.seqStream.isInstanceOf[IntStream]) - assert(hsI.parStream.isInstanceOf[IntStream]) +// assertEq(seqI, hsI.seqStream.toScala(Seq.sorted) +// assertEq(seqI, hsI.parStream.toScala(Seq.sorted) +// assert(hsI.seqStream.isInstanceOf[IntStream]) +// assert(hsI.parStream.isInstanceOf[IntStream]) val arrL = arrayL(n) val seqL = arrL.toSeq @@ -229,64 +227,42 @@ class StreamConvertersTest { val wrL = wrapL(n) val vecL = vectL(n) val hsL = hsetL(n) - assertEq(seqL, seqL.seqStream.toScala[Seq]) - //assertEq(seqL, seqL.stepper.parStream.toScala[Seq]) - assertEq(seqL, arrL.seqStream.toScala[Seq]) - assertEq(seqL, arrL.parStream.toScala[Seq]) + assertEq(seqL, seqL.seqStream.toScala(Seq)) +// assertEq(seqL, seqL.stepper.parStream.toScala(Seq) + assertEq(seqL, arrL.seqStream.toScala(Seq)) + assertEq(seqL, arrL.parStream.toScala(Seq)) assert(arrL.seqStream.isInstanceOf[LongStream]) assert(arrL.parStream.isInstanceOf[LongStream]) - assertEq(seqL, abL.seqStream.toScala[Seq]) - assertEq(seqL, abL.parStream.toScala[Seq]) + assertEq(seqL, abL.seqStream.toScala(Seq)) + assertEq(seqL, abL.parStream.toScala(Seq)) assert(abL.seqStream.isInstanceOf[LongStream]) assert(abL.parStream.isInstanceOf[LongStream]) - assertEq(seqD, wrD.seqStream.toScala[Seq]) - assertEq(seqD, wrD.parStream.toScala[Seq]) + assertEq(seqD, wrD.seqStream.toScala(Seq)) + assertEq(seqD, wrD.parStream.toScala(Seq)) assert(wrL.seqStream.isInstanceOf[LongStream]) assert(wrL.parStream.isInstanceOf[LongStream]) - assertEq(seqD, wrD.seqStream.toScala[Seq]) - assertEq(seqD, wrD.parStream.toScala[Seq]) + assertEq(seqD, wrD.seqStream.toScala(Seq)) + assertEq(seqD, wrD.parStream.toScala(Seq)) assert(vecL.seqStream.isInstanceOf[LongStream]) assert(vecL.parStream.isInstanceOf[LongStream]) - assertEq(seqL, hsL.seqStream.toScala[Seq].sorted) - assertEq(seqL, hsL.parStream.toScala[Seq].sorted) - assert(hsL.seqStream.isInstanceOf[LongStream]) - assert(hsL.parStream.isInstanceOf[LongStream]) +// assertEq(seqL, hsL.seqStream.toScala(Seq.sorted) +// assertEq(seqL, hsL.parStream.toScala(Seq.sorted) +// assert(hsL.seqStream.isInstanceOf[LongStream]) +// assert(hsL.parStream.isInstanceOf[LongStream]) } } @Test def primitiveStreamTypes(): Unit = { // Unboxed native + widening Steppers available: - assertEquals(Vector[Int](1, 2, 3), (Array[Int](1, 2, 3).seqStream: IntStream).toScala[Vector]) - assertEquals(Vector[Short](1.toShort, 2.toShort, 3.toShort), (Array[Short](1.toShort, 2.toShort, 3.toShort).seqStream: IntStream).toScala[Vector]) - assertEquals(Vector[String]("a", "b"), (Array[String]("a", "b").seqStream: Stream[String]).toScala[Vector]) + assertEquals(Vector[Int](1, 2, 3), (Array[Int](1, 2, 3).seqStream: IntStream).toScala(Vector)) + assertEquals(Vector[Short](1.toShort, 2.toShort, 3.toShort), (Array[Short](1.toShort, 2.toShort, 3.toShort).seqStream: IntStream).toScala(Vector)) + assertEquals(Vector[String]("a", "b"), (Array[String]("a", "b").seqStream: Stream[String]).toScala(Vector)) // Boxed collections, widening via boxed AnySteppers: - assertEquals(Vector[Int](1, 2, 3), (Vector[Int](1, 2, 3).seqStream: IntStream).toScala[Vector]) - assertEquals(Vector[Short](1.toShort, 2.toShort, 3.toShort), (Vector[Short](1.toShort, 2.toShort, 3.toShort).seqStream: IntStream).toScala[Vector]) - assertEquals(Vector[String]("a", "b"), (Vector[String]("a", "b").seqStream: Stream[String]).toScala[Vector]) - } - - @Test - def streamMaterialization(): Unit = { - val coll = collection.mutable.WrappedArray.make[Int](Array(1,2,3)) - val streamize = implicitly[collection.mutable.WrappedArray[Int] => MakesSequentialStream[Int, IntStream]] - assertTrue(streamize(coll).getClass.getName.contains("EnrichIntWrappedArrayWithStream")) - val steppize = implicitly[collection.mutable.WrappedArray[Int] => MakesStepper[Int, Any]] - assertTrue(steppize(coll).getClass.getName.contains("RichArrayCanStep")) - val stepper = steppize(coll).stepper - assertTrue(stepper.getClass.getName.contains("StepsIntArray")) - - val ss = Vector(1,2,3).seqStream - val ss2: IntStream = ss - - val coll2 = Vector(1,2,3) - val streamize2 = implicitly[Vector[Int] => MakesSequentialStream[Int, IntStream]] - assertTrue(streamize2(coll2).getClass.getName.contains("EnrichAnySteppableWithSeqStream")) - val steppize2 = implicitly[Vector[Int] => MakesStepper[Int, Any]] - assertTrue(steppize2(coll2).getClass.getName.contains("RichVectorCanStep")) - val stepper2 = steppize2(coll2).stepper - assertTrue(stepper2.getClass.getName.contains("StepsIntVector")) + assertEquals(Vector[Int](1, 2, 3), (Vector[Int](1, 2, 3).seqStream: IntStream).toScala(Vector)) + assertEquals(Vector[Short](1.toShort, 2.toShort, 3.toShort), (Vector[Short](1.toShort, 2.toShort, 3.toShort).seqStream: IntStream).toScala(Vector)) + assertEquals(Vector[String]("a", "b"), (Vector[String]("a", "b").seqStream: Stream[String]).toScala(Vector)) } @Test