scala.jdk
package scala.jdk
Type members
Classlikes
abstract class Accumulator[@specialized(Double, Int, Long) A, +CC <: ([X] =>> Seq[X]), +C <: Seq[A]] extends Seq[A] with Builder[A, C]
Accumulators are mutable sequences with two distinct features:
-
An accumulator can be appended efficiently to another
-
There are manually specialized Accumulators for
Int
,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. 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
Int => Int)* 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.
object Accumulator
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)
final class AnyAccumulator[A] extends Accumulator[A, [A] =>> AnyAccumulator[A], AnyAccumulator[A]] with SeqOps[A, [A] =>> AnyAccumulator[A], AnyAccumulator[A]] with IterableFactoryDefaults[A, [A] =>> AnyAccumulator[A]] with Serializable
An Accumulator for arbitrary element types, see Accumulator.
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
- (source)
final class DoubleAccumulator extends Accumulator[Double, [A] =>> AnyAccumulator[A], DoubleAccumulator] with SeqOps[Double, [A] =>> AnyAccumulator[A], DoubleAccumulator] with Serializable
A specialized Accumulator that holds
Double
s without boxing, see Accumulator. object DurationConverters
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
- (source)
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
- (source)
object FutureConverters
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
CompletionStage
s.
- Source
- (source)
final class IntAccumulator extends Accumulator[Int, [A] =>> AnyAccumulator[A], IntAccumulator] with SeqOps[Int, [A] =>> AnyAccumulator[A], IntAccumulator] with Serializable
A specialized Accumulator that holds
Int
s without boxing, see Accumulator.final class LongAccumulator extends Accumulator[Long, [A] =>> AnyAccumulator[A], LongAccumulator] with SeqOps[Long, [A] =>> AnyAccumulator[A], LongAccumulator] with Serializable
A specialized Accumulator that holds
Long
s without boxing, see Accumulator. object OptionConverters
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
- (source)
@implicitNotFound("No specialized Optional type exists for elements of type ${A}")
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
- (source)