The jdk package contains utilities to interact with JDK classes.
This packages offers a number of converters, that are able to wrap or copy types from the scala library to equivalent types in the JDK class library and vice versa:
-CollectionConverters, converting collections likescala.collection.Seq,scala.collection.Map,scala.collection.Set,scala.collection.mutable.Buffer,scala.collection.Iterator andscala.collection.Iterable to their JDK counterparts -OptionConverters, converting betweenOption andjava.util.Optional and primitive variations -StreamConverters, to create JDK Streams from scala collections -DurationConverters, for conversions between scalascala.concurrent.duration.FiniteDuration andjava.time.Duration -FunctionConverters, from scala Functions to javajava.util.function.Function,java.util.function.UnaryOperator,java.util.function.Consumer andjava.util.function.Predicate, as well as primitive variations and Bi-variations.
By convention, converters that wrap an object to provide a different interface to the same underlying data structure use .asScala and .asJava extension methods, whereas converters that copy the underlying data structure use .toScala and .toJava.
In thejavaapi package, the same converters can be found with a java-friendly interface that don't rely on implicit enrichments.
Additionally, this package offersAccumulators, capable of efficiently traversing JDK Streams.
Accumulators are mutable sequences with two distinct features:
Accumulators are mutable sequences with two distinct features:
An accumulator can be appended efficiently to another
There are manually specialized Accumulators forInt,Long andDouble that don't box the elements
These two features make Accumulators a good candidate to collect the results of a parallel Java stream pipeline into a Scala collection. Thescala.collection.convert.StreamExtensions.StreamHasToScala.toScala extension method on Java streams (available by importingscala.jdk.StreamConverters._) is specialized for Accumulators: they are built in parallel, the parts are merged efficiently.
Building specialized Accumulators is handled transparently. As a user, using theAccumulator object as a factory automatically creates anIntAccumulator,LongAccumulator,DoubleAccumulator orAnyAccumulator depending on the element type.
Note: to run the example, start the Scala REPL withscala -Yrepl-class-based to avoid deadlocks, seehttps://github.com/scala/bug/issues/9076.
scala> import scala.jdk.StreamConverters._import scala.jdk.StreamConverters._scala> def isPrime(n: Int): Boolean = !(2 +: (3 to Math.sqrt(n).toInt by 2) exists (n % _ == 0))isPrime: (n: Int)Booleanscala> val intAcc = (1 to 10000).asJavaParStream.filter(isPrime).toScala(scala.jdk.Accumulator)intAcc: scala.jdk.IntAccumulator = IntAccumulator(1, 3, 5, 7, 11, 13, 17, 19, ...scala> val stringAcc = (1 to 100).asJavaParStream.mapToObj("<>" * _).toScala(Accumulator)stringAcc: scala.jdk.AnyAccumulator[String] = AnyAccumulator(<>, <><>, <><><>, ...There are two possibilities to process elements of a primitive Accumulator without boxing: specialized operations of the Accumulator, or the Stepper interface. The most common collection operations are overloaded or overridden in the primitive Accumulator classes, for exampleIntAccumulator.map orIntAccumulator.exists. Thanks to Scala's function specialization,intAcc.exists(x => testOn(x)) does not incur boxing.
Thescala.collection.Stepper interface provides iterator-likehasStep andnextStep methods, and is specialized forInt,Long andDouble. TheintAccumulator.stepper method creates anscala.collection.IntStepper that yields the elements of the accumulator without boxing.
Accumulators can hold more thanInt.MaxValue elements. They have asizeLong method that returns the size as aLong. Note that certain operations defined inscala.collection.Seq are implemented usinglength, so they will not work correctly for large accumulators.
TheAccumulator class is a base class to share code betweenAnyAccumulator (for reference types) and the manual specializationsIntAccumulator,LongAccumulator andDoubleAccumulator.
Contains factory methods to build Accumulators.
Contains factory methods to build Accumulators.
Note that theAccumulator object itself is not a factory, but it is implicitly convert to a factory according to the element type, seeAccumulator.toFactory.
This allows passing theAccumulator object as argument when acollection.Factory, and the implicitAccumulator.AccumulatorFactoryShape instance is used to build a specialized Accumulator according to the element type:
scala> val intAcc = Accumulator(1,2,3)intAcc: scala.collection.convert.IntAccumulator = IntAccumulator(1, 2, 3)scala> val anyAccc = Accumulator("K")anyAccc: scala.collection.convert.AnyAccumulator[String] = AnyAccumulator(K)scala> val intAcc2 = List(1,2,3).to(Accumulator)intAcc2: scala.jdk.IntAccumulator = IntAccumulator(1, 2, 3)scala> val anyAcc2 = List("K").to(Accumulator)anyAcc2: scala.jdk.AnyAccumulator[String] = AnyAccumulator(K)An Accumulator for arbitrary element types, seeAccumulator.
An Accumulator for arbitrary element types, seeAccumulator.
This object provides extension methods that convert between Scala and Java collections.
This object provides extension methods that convert between Scala and Java collections.
When writing Java code, use the explicit conversion methods defined injavaapi.CollectionConverters instead.
Note: to createJava Streams that operate on Scala collections (sequentially or in parallel), useStreamConverters.
import scala.jdk.CollectionConverters._val s: java.util.Set[String] = Set("one", "two").asJavaThe conversions return adapters for the corresponding API, i.e., the collections are wrapped, not converted. Changes to the original collection are reflected in the view, and vice versa:
scala> import scala.jdk.CollectionConverters._scala> val s = collection.mutable.Set("one")s: scala.collection.mutable.Set[String] = HashSet(one)scala> val js = s.asJavajs: java.util.Set[String] = [one]scala> js.add("two")scala> sres2: scala.collection.mutable.Set[String] = HashSet(two, one)The following conversions are supported viaasScala andasJava:
scala.collection.Iterable <=> java.lang.Iterablescala.collection.Iterator <=> java.util.Iteratorscala.collection.mutable.Buffer <=> java.util.Listscala.collection.mutable.Set <=> java.util.Setscala.collection.mutable.Map <=> java.util.Mapscala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMapThe following conversions are supported viaasScala and through specially-named extension methods to convert to Java collections, as shown:
scala.collection.Iterable <=> java.util.Collection (via asJavaCollection)scala.collection.Iterator <=> java.util.Enumeration (via asJavaEnumeration)scala.collection.mutable.Map <=> java.util.Dictionary (via asJavaDictionary)In addition, the following one-way conversions are provided viaasJava:
scala.collection.Seq => java.util.Listscala.collection.mutable.Seq => java.util.Listscala.collection.Set => java.util.Setscala.collection.Map => java.util.MapThe following one way conversion is provided viaasScala:
java.util.Properties => scala.collection.mutable.MapIn all cases, converting from a source type to a target type and back again will return the original source object. For example:
import scala.jdk.CollectionConverters._val source = new scala.collection.mutable.ListBuffer[Int]val target: java.util.List[Int] = source.asJavaval other: scala.collection.mutable.Buffer[Int] = target.asScalaassert(source eq other)A specialized Accumulator that holdsDoubles without boxing, seeAccumulator.
A specialized Accumulator that holdsDoubles without boxing, seeAccumulator.
This object provides extension methods that convert between Scala and Java duration types.
This object provides extension methods that convert between Scala and Java duration types.
When writing Java code, use the explicit conversion methods defined injavaapi.DurationConverters instead.
This object provides extension methods that convert between Scala and Java function types.
This object provides extension methods that convert between Scala and Java function types.
When writing Java code, use the explicit conversion methods defined injavaapi.FunctionConverters instead.
Using the.asJava extension method on a Scala function produces the most specific possible Java function type:
scala> import scala.jdk.FunctionConverters._scala> val f = (x: Int) => x + 1scala> val jf1 = f.asJavajf1: java.util.function.IntUnaryOperator = ...More generic Java function types can be created using the correspondingasJavaXYZ extension method:
scala> val jf2 = f.asJavaFunctionjf2: java.util.function.Function[Int,Int] = ...scala> val jf3 = f.asJavaUnaryOperatorjf3: java.util.function.UnaryOperator[Int] = ...Converting a Java function to Scala is done using theasScala extension method:
scala> List(1,2,3).map(jf2.asScala)res1: List[Int] = List(2, 3, 4)This object provides extension methods that convert between Scalascala.concurrent.Future and Javajava.util.concurrent.CompletionStage
This object provides extension methods that convert between Scalascala.concurrent.Future and Javajava.util.concurrent.CompletionStage
When writing Java code, use the explicit conversion methods defined injavaapi.FutureConverters instead.
Note that the bridge is implemented at the read-only side of asynchronous handles, namelyscala.concurrent.Future (instead ofscala.concurrent.Promise) andjava.util.concurrent.CompletionStage (instead ofjava.util.concurrent.CompletableFuture). This is intentional, as the semantics of bridging the write-handles would be prone to race conditions; if both ends (CompletableFuture andPromise) are completed independently at the same time, they may contain different values afterwards. For this reason,toCompletableFuture is not supported on the createdCompletionStages.
A specialized Accumulator that holdsInts without boxing, seeAccumulator.
A specialized Accumulator that holdsInts without boxing, seeAccumulator.
A specialized Accumulator that holdsLongs without boxing, seeAccumulator.
A specialized Accumulator that holdsLongs without boxing, seeAccumulator.
This object provides extension methods that convert between ScalaOption and JavaOptional types.
This object provides extension methods that convert between ScalaOption and JavaOptional types.
When writing Java code, use the explicit conversion methods defined injavaapi.OptionConverters instead.
ScalaOption is extended with atoJava method that creates a correspondingOptional, and atoJavaPrimitive method that creates a specialized variant (e.g.,OptionalInt) if applicable.
JavaOptional is extended with atoScala method and atoJavaPrimitive method.
Finally, specializedOptional types are extended withtoScala andtoJavaGeneric methods.
Example usage:
import scala.jdk.OptionConverters._val a = Option("example").toJava // Creates java.util.Optional[String] containing "example"val b = (None: Option[String]).toJava // Creates an empty java.util.Optional[String]val c = a.toScala // Back to Option("example")val d = b.toScala // Back to None typed as Option[String]val e = Option(2.7).toJava // java.util.Optional[Double] containing boxed 2.7val f = Option(2.7).toJavaPrimitive // java.util.OptionalDouble containing 2.7 (not boxed)val g = f.toScala // Back to Option(2.7)val h = f.toJavaGeneric // Same as eval i = e.toJavaPrimitive // Same as fA type class implementing conversions from a generic ScalaOption or JavaOptional to a specialized Java variant (forDouble,Int andLong).
A type class implementing conversions from a generic ScalaOption or JavaOptional to a specialized Java variant (forDouble,Int andLong).
the primitive type wrapped in an option
the specialized JavaOptional wrapping an element of typeA
This object provides extension methods to createJava Streams that operate on Scala collections (sequentially or in parallel).
This object provides extension methods to createJava Streams that operate on Scala collections (sequentially or in parallel). For more information on Java streams, consult the documentation (https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html).
When writing Java code, use the explicit conversion methods defined injavaapi.StreamConverters instead.
The methodsasJavaSeqStream andasJavaParStream convert a collection to a Java Stream:
scala> import scala.jdk.StreamConverters._scala> val s = (1 to 10).toList.asJavaSeqStreams: java.util.stream.IntStream = java.util.stream.IntPipeline$Head@7b1e5e55scala> s.map(_ * 2).filter(_ > 5).toScala(List)res1: List[Int] = List(6, 8, 10, 12, 14, 16, 18, 20)Note: using parallel streams in the Scala REPL causes deadlocks, seehttps://github.com/scala/bug/issues/9076. As a workaround, usescala -Yrepl-class-based.
scala> def isPrime(n: Int): Boolean = !(2 +: (3 to Math.sqrt(n).toInt by 2) exists (n % _ == 0))isPrime: (n: Int)Booleanscala> (10000 to 1000000).asJavaParStream.filter(isPrime).toScala(Vector)res6: scala.collection.immutable.Vector[Int] = Vector(10007, 10009, 10037, 10039, ...A JavaStream provides operations on a sequence of elements. Streams are created fromSpliterators, which are similar to Iterators with the additional capability to partition off some of their elements. This partitioning, if supported by the Spliterator, is used for parallelizing Stream operations.
Scala collections have a methodstepper that returns ascala.collection.Stepper for the collection, which in turn can be converted to a Spliterator for creating a Java Stream.
TheasJavaSeqStream extension method is available on any Scala collection. TheasJavaParStream extension method can only be invoked on collections where the return type of thestepper method is marked with thescala.collection.Stepper.EfficientSplit marker trait. This trait is added to steppers that support partitioning, and therefore efficient parallel processing.
The following extension methods are available:
Collection Type | Extension Methods |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Strings |
|
Java streams |
|
TheasJavaPrimitiveStream method converts aStream[Int] to anIntStream. It is the dual of theboxed method defined on primitive streams (e.g.,IntStream.boxed is aStream[Integer]).
ThetoScala extension methods on Java streams collects the result of a stream pipeline into a Scala collection, for examplestream.toScala(List),stream.toScala(Vector). Note that transformation operations on streams are lazy (also called "intermediate"), terminal operations such asforEach,count ortoScala trigger the evaluation.
Collecting a parallel stream to a collection can be performed in parallel. This is beneficial if the target collection supports efficient merging of the segments that are built in parallel. To support this use case, the Scala standard library provides theAccumulator collection. This collection supports efficient parallel construction, and it has specialized subtypes forInt,Long andDouble so that primitive Java streams can be collected to a Scala collection without boxing the elements.