scala.jdk

package scala.jdk

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 like scala.collection.Seq, scala.collection.Map, scala.collection.Set, scala.collection.mutable.Buffer, scala.collection.Iterator and scala.collection.Iterable to their JDK counterparts - OptionConverters, converting between Option and java.util.Optional and primitive variations - StreamConverters, to create JDK Streams from scala collections - DurationConverters, for conversions between scala scala.concurrent.duration.FiniteDuration and java.time.Duration - FunctionConverters, from scala Functions to java java.util.function.Function, java.util.function.UnaryOperator, java.util.function.Consumer and java.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 the javaapi package, the same converters can be found with a java-friendly interface that don't rely on implicit enrichments.

Additionally, this package offers Accumulators, capable of efficiently traversing JDK Streams.

Type members

Classlikes

abstract class Accumulator[A, +CC <: (Seq), +C <: Seq[A]] extends Seq[A] with Builder[A, C]

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 for Int, Long and Double 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. The scala.collection.convert.StreamExtensions.StreamHasToScala.toScala extension method on Java streams (available by importing scala.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 the Accumulator object as a factory automatically creates an IntAccumulator, LongAccumulator, DoubleAccumulator or AnyAccumulator depending on the element type.

Note: to run the example, start the Scala REPL with scala -Yrepl-class-based to avoid deadlocks, see https://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)Boolean

scala> 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 example IntAccumulator.map or IntAccumulator.exists. Thanks to Scala's function specialization, intAcc.exists(x => testOn(x)) does not incur boxing.

The scala.collection.Stepper interface provides iterator-like hasStep and nextStep methods, and is specialized for Int, Long and Double. The intAccumulator.stepper method creates an scala.collection.IntStepper that yields the elements of the accumulator without boxing.

Accumulators can hold more than Int.MaxValue elements. They have a sizeLong method that returns the size as a Long. Note that certain operations defined in scala.collection.Seq are implemented using length, so they will not work correctly for large accumulators.

The Accumulator class is a base class to share code between AnyAccumulator (for reference types) and the manual specializations IntAccumulator, LongAccumulator and DoubleAccumulator.

Companion:
object
Source:
Accumulator.scala

Contains factory methods to build Accumulators.

Contains factory methods to build Accumulators.

Note that the Accumulator object itself is not a factory, but it is implicitly convert to a factory according to the element type, see Accumulator.toFactory.

This allows passing the Accumulator object as argument when a collection.Factory, and the implicit Accumulator.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)
Companion:
class
Source:
Accumulator.scala

An Accumulator for arbitrary element types, see Accumulator.

An Accumulator for arbitrary element types, see Accumulator.

Companion:
object
Source:
AnyAccumulator.scala

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 in javaapi.CollectionConverters instead.

Note: to create Java Streams that operate on Scala collections (sequentially or in parallel), use StreamConverters.

import scala.jdk.CollectionConverters._
val s: java.util.Set[String] = Set("one", "two").asJava

The 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.asJava
js: java.util.Set[String] = [one]

scala> js.add("two")

scala> s
res2: scala.collection.mutable.Set[String] = HashSet(two, one)

The following conversions are supported via asScala and asJava:

scala.collection.Iterable       <=> java.lang.Iterable
scala.collection.Iterator       <=> java.util.Iterator
scala.collection.mutable.Buffer <=> java.util.List
scala.collection.mutable.Set    <=> java.util.Set
scala.collection.mutable.Map    <=> java.util.Map
scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap

The following conversions are supported via asScala 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 via asJava:

scala.collection.Seq         => java.util.List
scala.collection.mutable.Seq => java.util.List
scala.collection.Set         => java.util.Set
scala.collection.Map         => java.util.Map

The following one way conversion is provided via asScala:

java.util.Properties => scala.collection.mutable.Map

In 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.asJava
val other: scala.collection.mutable.Buffer[Int] = target.asScala
assert(source eq other)
Source:
CollectionConverters.scala

A specialized Accumulator that holds Doubles without boxing, see Accumulator.

A specialized Accumulator that holds Doubles without boxing, see Accumulator.

Companion:
object
Source:
DoubleAccumulator.scala

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 in javaapi.DurationConverters instead.

Source:
DurationConverters.scala

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 in javaapi.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 + 1

scala> val jf1 = f.asJava
jf1: java.util.function.IntUnaryOperator = ...

More generic Java function types can be created using the corresponding asJavaXYZ extension method:

scala> val jf2 = f.asJavaFunction
jf2: java.util.function.Function[Int,Int] = ...

scala> val jf3 = f.asJavaUnaryOperator
jf3: java.util.function.UnaryOperator[Int] = ...

Converting a Java function to Scala is done using the asScala extension method:

scala> List(1,2,3).map(jf2.asScala)
res1: List[Int] = List(2, 3, 4)
Source:
FunctionConverters.scala

This object provides extension methods that convert between Scala scala.concurrent.Future and Java java.util.concurrent.CompletionStage

This object provides extension methods that convert between Scala scala.concurrent.Future and Java java.util.concurrent.CompletionStage

When writing Java code, use the explicit conversion methods defined in javaapi.FutureConverters instead.

Note that the bridge is implemented at the read-only side of asynchronous handles, namely scala.concurrent.Future (instead of scala.concurrent.Promise) and java.util.concurrent.CompletionStage (instead of java.util.concurrent.CompletableFuture). This is intentional, as the semantics of bridging the write-handles would be prone to race conditions; if both ends (CompletableFuture and Promise) are completed independently at the same time, they may contain different values afterwards. For this reason, toCompletableFuture is not supported on the created CompletionStages.

Source:
FutureConverters.scala

A specialized Accumulator that holds Ints without boxing, see Accumulator.

A specialized Accumulator that holds Ints without boxing, see Accumulator.

Companion:
object
Source:
IntAccumulator.scala

A specialized Accumulator that holds Longs without boxing, see Accumulator.

A specialized Accumulator that holds Longs without boxing, see Accumulator.

Companion:
object
Source:
LongAccumulator.scala

This object provides extension methods that convert between Scala Option and Java Optional types.

This object provides extension methods that convert between Scala Option and Java Optional types.

When writing Java code, use the explicit conversion methods defined in javaapi.OptionConverters instead.

Scala Option is extended with a toJava method that creates a corresponding Optional, and a toJavaPrimitive method that creates a specialized variant (e.g., OptionalInt) if applicable.

Java Optional is extended with a toScala method and a toJavaPrimitive method.

Finally, specialized Optional types are extended with toScala and toJavaGeneric 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.7
val 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 e
val i = e.toJavaPrimitive             // Same as f
Source:
OptionConverters.scala
sealed abstract class OptionShape[A, O]

A type class implementing conversions from a generic Scala Option or Java Optional to a specialized Java variant (for Double, Int and Long).

A type class implementing conversions from a generic Scala Option or Java Optional to a specialized Java variant (for Double, Int and Long).

Type parameters:
A

the primitive type wrapped in an option

O

the specialized Java Optional wrapping an element of type A

Companion:
object
Source:
OptionShape.scala
Companion:
class
Source:
OptionShape.scala

This object provides extension methods to create Java Streams that operate on Scala collections (sequentially or in parallel).

This object provides extension methods to create Java 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 in javaapi.StreamConverters instead.

The methods asJavaSeqStream and asJavaParStream convert a collection to a Java Stream:

scala> import scala.jdk.StreamConverters._

scala> val s = (1 to 10).toList.asJavaSeqStream
s: java.util.stream.IntStream = java.util.stream.IntPipeline$Head@7b1e5e55

scala> 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, see https://github.com/scala/bug/issues/9076. As a workaround, use scala -Yrepl-class-based.

scala> def isPrime(n: Int): Boolean = !(2 +: (3 to Math.sqrt(n).toInt by 2) exists (n % _ == 0))
isPrime: (n: Int)Boolean

scala> (10000 to 1000000).asJavaParStream.filter(isPrime).toScala(Vector)
res6: scala.collection.immutable.Vector[Int] = Vector(10007, 10009, 10037, 10039, ...

A Java Stream provides operations on a sequence of elements. Streams are created from Spliterators, 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 method stepper that returns a scala.collection.Stepper for the collection, which in turn can be converted to a Spliterator for creating a Java Stream.

The asJavaSeqStream extension method is available on any Scala collection. The asJavaParStream extension method can only be invoked on collections where the return type of the stepper method is marked with the scala.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

IterableOnce

asJavaSeqStream

IndexedSeq, Arrays, BitSet, Accumulator, HashMap, HashSet, Range, TreeMap, TreeSet, Vector, Strings

asJavaParStream

Map

asJavaSeqKeyStream, asJavaSeqValueStream

HashMap, TreeMap

asJavaParKeyStream, asJavaParValueStream

Stepper

asJavaSeqStream

Stepper with EfficientSplit

asJavaParStream

Strings

asJavaSeqStream, asJavaParStream, asJavaSeqCharStream, asJavaParCharStream, asJavaSeqCodePointStream, asJavaParCodePointStream

Java streams

toScala, asJavaPrimitiveStream

The asJavaPrimitiveStream method converts a Stream[Int] to an IntStream. It is the dual of the boxed method defined on primitive streams (e.g., IntStream.boxed is a Stream[Integer]).

The toScala extension methods on Java streams collects the result of a stream pipeline into a Scala collection, for example stream.toScala(List), stream.toScala(Vector). Note that transformation operations on streams are lazy (also called "intermediate"), terminal operations such as forEach, count or toScala 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 the Accumulator collection. This collection supports efficient parallel construction, and it has specialized subtypes for Int, Long and Double so that primitive Java streams can be collected to a Scala collection without boxing the elements.

Source:
StreamConverters.scala