Published 2014-03-10.
Last modified 2019-07-18.
Time to read: 2 minutes.
Scala has long had the to[]
copy constructor, which operates on one type of collections and returns another type; Scala 2.13 changed the syntax to use parentheses: to()
.
The code for this lecture is provided in collections.ConverterFun
.
Every Scala collection type inherits a method called to
from the IterableOnce
trait.
The to
method converts the collection to another type.
This method was first mentioned in the Collections Overview lecture.
Most of these conversion methods return a copy of the original data, but sometimes the data is merely wrapped, which saves processing time and memory; details vary depending on the type of collections being converted from and to.
Following are some examples.
We can convert between Array
and List
.
scala> scala> Array(1).to(List) res1: List[Int] = List(1)
scala> scala> List(1).to(Array) res2: Array[Int] = Array(1)
...
and convert from an Iterator
to a List
.
scala> scala> val iter = io.Source.fromFile("build.sbt").getLines iter: Iterator[String] = non-empty iterator
scala> scala> iter.to(List) res3: List[String] = List(organization := "com.micronautics", "", name := "IntermediateScala Course", "", description := "Intermediate Scala Course Notes", "", version := "0.1.1", "", scalaVersion := "2.10.4", "", autoCompilerPlugins := true, "", libraryDependencies <+= scalaVersion {, " v => compilerPlugin("org.scala-lang.plugins" % "continuations" % "2.10.4")", }, "", scalacOptions += "-P:continuations:enable", "", scalacOptions in (Compile, doc) <++= baseDirectory.map {, " (bd: File) => Seq[String](", " "-deprecation",", " "-encoding", "UTF-8",", " "-unchecked",", " "-feature",", " "-target:jvm-1.6",", " "-sourcepath", bd.getAbsolutePath,", " "-Ywarn-adapted-args",", " "-doc-source-url", "https://bitbucket.org/mslinn/course_scala_intermediate_code/src/ma...
Conversion between immutable and mutable types is possible.
scala> scala> List(1).to(collection.mutable.Buffer) res4: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1)
scala> scala> scala.collection.mutable.Buffer(1).to(List) res5: List[Int] = List(1)
Conversion between Option
and List
is possible.
scala> scala> Some(1).to(List) res6: List[Int] = List(1)
Here is another syntax to accomplish the same thing.
scala> scala> Some(1).toList res7: List[Int] = List(1)
You cannot convert back the other way, because List
s that have more than one element have no counterpart with Option
.
scala> scala> List(1).to(Option) ^ error: type mismatch; found : Option.type required: scala.collection.Factory[Int,?]
The other convenience methods like toList
are: toArray
, toBuffer
, toIndexedSeq
, toMap
, toSeq
, toSet
, and toVector
.
Conversion between a list of tuples and an immutable.Map
is also supported.
scala> scala> List('a' -> 2).to(Map) res8: scala.collection.immutable.Map[Char,Int] = Map(a -> 2)
scala> scala> List('a' -> 2).toMap // does the same thing res9: scala.collection.immutable.Map[Char,Int] = Map(a -> 2)
scala> scala> Map('a' -> 2).toList res10: List[(Char, Int)] = List((a,2))
We can convert a Vector
to a LazyList
like this.
scala> scala> Vector(1, 1, 2, 2, 3, 3).to(LazyList) res11: scala.collection.immutable.LazyList[Int] = LazyList(?)
This is rather like making a view, which converts a strict collection into a lazy collection.
scala> scala> Vector(1, 1, 2, 2, 3, 3).view res12: scala.collection.IndexedSeqView[Int] = IndexedSeqView(<not computed>)
The documentation I linked to is old and has not yet been updated.
Let's see what happens when we try to convert from a view back to a strict list by using the force
method.
scala> scala> Vector(1, 1, 2, 2, 3, 3).view.force ^ warning: method force in trait View is deprecated (since 2.13.0): Views no longer know about their underlying collection type; .force always returns an IndexedSeq res1: scala.collection.IndexedSeq[Int] = Vector(1, 1, 2, 2, 3, 3)
We can ask for the type of collection that we want, however.
scala> scala> Vector(1, 1, 2, 2, 3, 3).view.toVector res13: scala.collection.immutable.Vector[Int] = Vector(1, 1, 2, 2, 3, 3)
Lots more conversions are possible.
scala> scala> List(1).to(Set) res14: scala.collection.immutable.Set[Int] = Set(1)
scala> scala> List(1).toSet // does the same thing res15: scala.collection.immutable.Set[Int] = Set(1)
scala> scala> Set(1).toList res16: List[Int] = List(1)
scala> scala> Set(1).to(scala.collection.immutable.BitSet) res17: scala.collection.immutable.BitSet = BitSet(1)
scala> scala> Array(1).to(scala.collection.immutable.BitSet) res18: scala.collection.immutable.BitSet = BitSet(1)
...
and many more! In fact, any collection that implements the scala.collection.Factory
trait supports the to
method.
We talked about parallel collections in the Parallel Collections lecture.
Here is how to convert from a single-threaded immutable.List
to a multithreaded set (ParSet
).
scala> scala> val parSet = List(1, 1, 2, 2, 3, 3).to(scala.collection.parallel.ParSet) parSet: scala.collection.parallel.ParSet[Int] = <function1>
scala> scala> parSet.sum res19: Int = 6
The above only works if the scala-parallel-collections
library is a dependency of the sbt project.
Iterable
also provides a toParArray
method for the special case of converting Array
s to parallel arrays.
As we saw in the Parallel Collections lecture, Iterable
's par
method converts collection subclasses to parallel versions of those collections, instead of defining dozens of toParXXX
methods.
© Copyright 1994-2024 Michael Slinn. All rights reserved.
If you would like to request to use this copyright-protected work in any manner,
please send an email.
This website was made using Jekyll and Mike Slinn’s Jekyll Plugins.