不可變與可變容器(Container)Syntax
scala> val demoSet = Set("HHH", "BBB")
demoSet: scala.collection.immutable.Set[java.lang.String] = Set(HHH, BBB)
scala> val set2 = Set("Hello", 'a')
set2: scala.collection.immutable.Set[Any] = Set(Hello, a)
scala> import scala.collection.mutable.Set
import scala.collection.mutable.Set
scala> val movieSet = Set("Hitch", "Poltergeist")
movieSet: scala.collection.mutable.Set[java.lang.String] = Set(Poltergeist, Hitch)
Scala中創建集的方法與創建列表和陣列的類似:通過調用Set伴生對象的名為apply的工廠方法。代碼3.5中,對
scala.collection.immutable.Set的伴生對象調用了apply方法,返回了一個缺省的,不可變Set的實例。Scala編譯
器推斷jetSet的類型為不可變Set[String]。
Generic: <> -> [ ]
數組表示為泛型化的 Array 類的實例,這正是 Scala 使用方括號(「[]」)而非尖括號(「<>」)來指明參數化類型的原因。
References
Because Scala aims to help you take advantage of both functional and imperative styles, its collections
libraries make a point to differentiate between mutable and immutable collection classes. For example,
Array
s are always mutable, whereas List
s are always immutable. When it comes to
Set
s and Map
s, Scala also provides mutable and immutable alternatives, but in a
different way. For Set
s and Map
s, Scala models mutability in the class hierarchy.
For example, the Scala API contains a base trait for Set
s, where a trait is similar to
a Java interface
. (You'll find out more about trait
s in Step 12.) Scala then
provides two subtraits, one for mutable Set
s, and another for immutable Set
s.
As you can see in Figure 2, these three traits all share the same simple name, Set
. Their
fully qualified names differ,
however, because they each reside in a different package.
Concrete Set
classes in the Scala API, such as the HashSet
classes shown in
Figure 2, extend either the mutable or immutable Set
trait. (Although in Java you
implement interface
s, in Scala you “extend” traits.) Thus, if you want to use a HashSet
,
you can choose between mutable and immutable varieties depending upon your needs.

Figure 2. Class hierarchy for Scala Set
s.
To try out Scala Set
s, type the following code into a file named jetset.scala
:
import scala.collection.mutable.HashSet
val jetSet = new HashSet[String]
jetSet += "Lear"
jetSet += ("Boeing", "Airbus")
println(jetSet.contains("Cessna"))
The first line of jetSet.scala
imports the mutable HashSet
. As with Java, the import
allows you to use the simple name of the class, HashSet
, in this source file.
After a blank line, the third line
initializes jetSet
with a new HashSet
that will contain only String
s.
Note that just as with List
s and Array
s, when you create a Set
, you
need to parameterize it with a type (in this case, String
), since
every object in a Set
must share the same type.
The subsequent two lines add three objects to the mutable Set
via the +=
method.
As with most other symbols you've seen that look like operators in Scala, +=
is actually a method defined on
class HashSet
. Had you wanted to, instead of writing jetSet += "Lear"
, you could have written
jetSet.+=("Lear")
.
Because the +=
method takes a variable number of arguments, you can pass one or more objects at a time to it.
For example, jetSet += "Lear"
adds one String
to the HashSet
, but
jetSet += ("Boeing", "Airbus")
adds two Strings
to the set.
Finally, the last line prints out whether
or not the Set
contains a particular String
. (As you'd expect, it prints false
.)
Another useful collection class in Scala is Map
s. As with Set
s, Scala provides mutable and
immutable versions of Map
, using a class hierarchy. As you can see in Figure 3, the class hierarchy for
Map
s looks a lot like the one for Set
s. There's a base Map
trait in
package scala.collection
, and two subtrait Map
s: a mutable Map
in
scala.collection.mutable
and an immutable one in scala.collection.immutable
.

Figure 3. Class hierarchy for Scala Map
s.
Implementations of Map
, such as the HashMap
s shown in the class hierarchy in Figure 3,
implement either the mutable or immutable trait. To see a Map
in action, type the following code
into a file named treasure.scala
.
// In treasure.scala
import scala.collection.mutable.HashMap
val treasureMap = new HashMap[Int, String]
treasureMap += 1 -> "Go to island."
treasureMap += 2 -> "Find big X on ground."
treasureMap += 3 -> "Dig."
println(treasureMap(2))
On the first line of treasure.scala
, you import the mutable form of HashMap
. After a blank line,
you define a val
named treasureMap
and initialize it with a new mutable HashMap
whose keys will be Int
s and values String
s.
On the next three lines you add key/value pairs to the HashMap
using
the ->
method. As illustrated in previous examples, the Scala compiler transforms an binary operation expression like
1 -> "Go to island."
into 1.->("Go to island.")
. Thus, when you say 1 -> "Go to island."
, you are actually calling a method
named ->
on
an Int
with the value 1, and passing in a String
with the value "Go to island."
This ->
method, which you can invoke on any object in a Scala program3,
returns a two-element tuple containing the key and value. You then pass this tuple to the +=
method of the HashMap
object to which treasureMap
refers.
Finally, the last line prints the value that corresponds to the key 2
in the treasureMap
. If you run this code,
it will print:
Find big X on ground.
Because maps are such a useful programming construct, Scala provides a factory method for Map
s that is similar in spirit
to the factory method shown in Step 9 that allows you to create List
s without using the new
keyword. To try out this more
concise way of constructing maps, type the following code into a file called numerals.scala
:
// In numerals.scala
val romanNumeral = Map(1 -> "I", 2 -> "II", 3 -> "III", 4 -> "IV", 5 -> "V")
println(romanNumeral(4))
In numerals.scala
you take advantage of the fact that the the immutable Map
trait is automatically imported into
any Scala source file. Thus when you say Map
in the first line of code, the Scala interpreter knows you mean scala.collection.immutable.Map
.
In this line, you call a factory method on the immutable Map
's companion object5, passing in five
key/value tuples as parameters. This factory method returns an instance of the immutable HashMap
containing
the passed key/value pairs. The name of the factory method is actually apply
, but as mentioned in Step 8, if you say Map(...)
it will
be transformed by the compiler to Map.apply(...)
. If you run the numerals.scala
script, it will print IV
.