Sets & Maps
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This page is written against Scala 3.10 (3.10.0, released 2026-10-12) and every example was compiled and run with Scala 3.10.0 through Scala CLI on JDK 26 (checked on 2026-10-15). Sets and maps belong to the collections library, whose API is the Scala 2.13 one (since 3.8 it is compiled by Scala 3 and versioned with the compiler), so the 3.9 LTS (3.9.0, 2026-09-03) and 3.3 LTS (3.3.8) lines behave the same way; see Scala 3.9 LTS versus 3.10.
A Set holds distinct elements and answers "is this in the set?". A Map associates distinct keys with values and answers
"what is the value for this key?". Both come in an immutable default (Set, Map with no import) and a mutable version in
scala.collection.mutable, with several implementations that differ in iteration order and in cost. The overall picture is on
Collections Overview; sequences are on
Sequences; the transformations (map, groupBy, foldLeft, …) are on
Collection Operations; costs are tabulated on
Collection Performance & Equality. The examples use the
trailhead scenario: peaks as sets and trail distances as maps. For the Java side see
the Java Collections Framework.
Which set or map
| You need | Set | Map |
|---|---|---|
Fast membership or lookup, order does not matter |
|
|
Sorted iteration, range queries |
|
|
Iteration in insertion order |
|
|
Small sets of integers |
|
Not applicable |
Updates in place |
|
|
Shared across threads |
|
|
Immutable Set
Set(...) builds an immutable set. + and - return a new set, contains tests membership, and the operators & (intersection),
| (union) and &~ (difference) mirror the named methods intersect, union and diff.
//> using scala 3.10.0
package trailhead
@main def sets(): Unit =
val peaks = Set("Alpina", "Rocca", "Alpina")
println(peaks)
println(peaks.size)
println(peaks + "Vetta")
println(peaks - "Rocca")
println(peaks.contains("Rocca"))
println(peaks("Rocca"))
println(peaks ++ Set("X", "Y"))
println(peaks.map(_.length))
println(Set(1, 2, 3) & Set(2, 3, 4))
println(Set(1, 2, 3) | Set(2, 3, 4))
println(Set(1, 2, 3) &~ Set(2, 3, 4))
println(Set(1, 2).subsetOf(Set(1, 2, 3)))
println(Set(1, 2) == Set(2, 1))
println(List(1, 2, 3).filter(Set(1, 2)))
println(Set(1, 2, 3, 4).getClass.getSimpleName)
println(Set(1, 2, 3, 4, 5).getClass.getSimpleName)
Set(Alpina, Rocca)
2
Set(Alpina, Rocca, Vetta)
Set(Alpina)
true
true
Set(Alpina, Rocca, X, Y)
Set(6, 5)
Set(2, 3)
Set(1, 2, 3, 4)
Set(1)
true
true
List(1, 2)
Set4
HashSet
A few details from the output. Duplicates in the literal are discarded: the first line has two elements, not three. map on a
set returns a set, so peaks.map(_.length) collapses two equal lengths if there were any. peaks("Rocca") is contains,
because a Set[A] is also a function A => Boolean; this is why filter(Set(1, 2)) works with a set as the predicate.
Sets of up to four elements use specialised classes (Set1 to Set4, here Set4) that keep insertion order; from five
elements the class is HashSet, a hash trie whose iteration order is unspecified.
Mutable Set
A mutable.Set changes in place: += adds, -= removes, ++= adds many, and add and remove return a Boolean that tells
whether the set changed, which is convenient for "seen before" checks.
//> using scala 3.10.0
package trailhead
import scala.collection.mutable
@main def mutableSets(): Unit =
val s = mutable.Set(1, 2)
s += 3
s ++= List(4, 5)
println(s)
println(s.add(3))
println(s.add(6))
println(s.remove(1))
s -= 2
println(s)
s.filterInPlace(_ > 3)
println(s)
val lhs = mutable.LinkedHashSet("c", "a", "b")
println(lhs)
var imm = Set(1, 2)
imm += 3
println(imm)
HashSet(1, 2, 3, 4, 5)
false
true
true
HashSet(3, 4, 5, 6)
HashSet(4, 5, 6)
LinkedHashSet(c, a, b)
Set(1, 2, 3)
The default mutable.Set is a mutable.HashSet. mutable.LinkedHashSet keeps insertion order. The last two lines compare with
a var holding an immutable Set: imm += 3 is rewritten by the compiler to imm = imm + 3, a new set each time, which is
fine for small, local state. If a val held the set that rewrite would not compile.
Source: Collections 2.13: Sets
Sorted sets: TreeSet, and BitSet
TreeSet is an immutable red-black tree that keeps its elements ordered by an Ordering; SortedSet(...) builds one. Besides
the ordinary set operations it offers range, rangeFrom, rangeUntil, rangeTo, firstKey, lastKey and iteratorFrom. A custom
ordering is passed with using. BitSet is a set of small non-negative integers stored as bits; ListSet is a set backed by a
list that keeps insertion order but has linear lookup and is only suitable for very small sets.
//> using scala 3.10.0
package trailhead
import scala.collection.immutable.{BitSet, ListSet, SortedSet, TreeSet}
@main def sortedSets(): Unit =
val ts = TreeSet(5, 1, 3)
println(ts)
println(ts.range(2, 5))
println(ts.rangeFrom(3))
println(ts.rangeUntil(3))
println(ts.rangeTo(3))
println(ts.firstKey)
println(ts.lastKey)
println(ts + 2)
println(ts.iteratorFrom(2).toList)
println(TreeSet(5, 1, 3)(using Ordering[Int].reverse))
println(SortedSet("pass", "ridge", "falls"))
val bs = BitSet(1, 5, 3, 64, 200)
println(bs)
println(bs.contains(5))
println(bs + 7)
println(ListSet(3, 1, 2))
TreeSet(1, 3, 5)
TreeSet(3)
TreeSet(3, 5)
TreeSet(1)
TreeSet(1, 3)
1
5
TreeSet(1, 2, 3, 5)
List(3, 5)
TreeSet(5, 3, 1)
TreeSet(falls, pass, ridge)
BitSet(1, 3, 5, 64, 200)
true
BitSet(1, 3, 5, 7, 64, 200)
ListSet(3, 1, 2)
All sorted operations take logarithmic time. The key type needs an implicit Ordering; for custom classes either define a given
Ordering or make the class Ordered, see Type Classes. A BitSet stores one bit per
possible element, so its size is proportional to the largest element (the set 1, 5, 3, 64, 200 needs four 64-bit words); it
is excellent for dense small integers and wasteful for a few large ones.
Immutable Map
A Map[K, V] is built from (key, value) pairs, most readably written with ->. Lookup with m(k) throws when the key is
missing; get returns an Option and getOrElse returns a default (evaluated only when the key is missing, because the
parameter is by-name). + and updated add or replace one entry, - and removedAll remove, and ++ merges, with the
right operand winning on conflicts.
//> using scala 3.10.0
package trailhead
@main def maps(): Unit =
val km = Map("Ridge" -> 12.5, "Falls" -> 4.0, "Pass" -> 8.25)
println(km("Ridge"))
println(km.get("Falls"))
println(km.get("Lake"))
println(km.getOrElse("Lake", 0.0))
println(km.contains("Pass"))
println(km + ("Lake" -> 3.0))
println(km - "Pass")
println(km ++ Map("Pass" -> 9.0, "Hut" -> 1.0))
println(km.updated("Ridge", 13.0))
println(km.keys)
println(km.values)
println(km.keySet)
println(km.map((k, v) => k -> v * 2))
println(km.view.mapValues(_ * 2).toMap)
println(km.filter((_, v) => v > 5))
println(km.toList)
println(km.removedAll(List("Pass", "Falls")))
println(km.updatedWith("Ridge")(_.map(_ + 1)))
println(km.updatedWith("Lake")(_ => Some(2.0)))
println(km.updatedWith("Pass")(_ => None))
12.5
Some(4.0)
None
0.0
true
Map(Ridge -> 12.5, Falls -> 4.0, Pass -> 8.25, Lake -> 3.0)
Map(Ridge -> 12.5, Falls -> 4.0)
Map(Ridge -> 12.5, Falls -> 4.0, Pass -> 9.0, Hut -> 1.0)
Map(Ridge -> 13.0, Falls -> 4.0, Pass -> 8.25)
Set(Ridge, Falls, Pass)
Iterable(12.5, 4.0, 8.25)
Set(Ridge, Falls, Pass)
Map(Ridge -> 25.0, Falls -> 8.0, Pass -> 16.5)
Map(Ridge -> 25.0, Falls -> 8.0, Pass -> 16.5)
Map(Ridge -> 12.5, Pass -> 8.25)
List((Ridge,12.5), (Falls,4.0), (Pass,8.25))
Map(Ridge -> 12.5)
Map(Ridge -> 13.5, Falls -> 4.0, Pass -> 8.25)
Map(Ridge -> 12.5, Falls -> 4.0, Pass -> 8.25, Lake -> 2.0)
Map(Ridge -> 12.5, Falls -> 4.0)
Source: Scala 3 Book: Maps and Collections 2.13: Maps
km.keys is an Iterable, km.keySet a Set, km.values an Iterable. Mapping a Map with a function that returns a pair
(k -> v * 2) gives a Map; with a function that returns anything else the result is an Iterable. Scala 3 accepts the
parameter-untupling form (k, v) => ... for functions over pairs, which Scala 2 did not, so no case (k, v) is needed.
updatedWith(key)(f) is the one-step update: f receives Some(oldValue) or None and returns Some(newValue) to set or
None to remove. It replaces the get-then-updated pattern and it is the Scala counterpart of Java’s Map.compute. The
same method exists on mutable.Map as updateWith.
Asking for a missing key throws, with a message that names the key:
//> using scala 3.10.0
@main def missing(): Unit =
val km = Map("Ridge" -> 12.5)
println(km("Lake"))
Exception in thread "main" java.util.NoSuchElementException: key not found: Lake
at scala.collection.immutable.Map$Map1.apply(Map.scala:291)
at missing$package$.missing(missing.scala:4)
at missing.main(missing.scala:2)
Source: Scala 3 Book: Maps and Collections 2.13: Maps
Maps and sets as functions
A Map[K, V] is a PartialFunction[K, V] and a Set[A] is a Function1[A, Boolean], so either can be passed where a function
is expected. collect(map) keeps only the keys that are present and replaces them with their values; map(m.lift) produces
Option values; filterNot(set) drops the members; applyOrElse is the one-call default.
//> using scala 3.10.0
package trailhead
@main def asFunctions(): Unit =
val km = Map("Ridge" -> 12.5, "Falls" -> 4.0)
val closed = Set("Pass", "Lake")
println(List("Ridge", "Lake", "Falls").collect(km))
println(List("Ridge", "Lake", "Falls").map(km.lift))
println(List("Ridge", "Pass", "Falls").filterNot(closed))
println(List("Ridge", "Lake").map(km.getOrElse(_, 0.0)))
println(km.applyOrElse("Lake", _ => -1.0))
val nested = Map("a" -> Map("x" -> 1))
println(nested.get("a").flatMap(_.get("x")))
println(nested.getOrElse("b", Map.empty).get("x"))
println(km.view.filterKeys(_.startsWith("R")).toMap)
println(km.maxBy(_._2))
println(km.toSeq.sortBy(-_._2).map(_._1))
println(km.foldLeft(0.0)((acc, kv) => acc + kv._2))
println(km.keySet.intersect(Set("Ridge", "Lake")))
List(12.5, 4.0)
List(Some(12.5), None, Some(4.0))
List(Ridge, Falls)
List(12.5, 0.0)
-1.0
Some(1)
None
Map(Ridge -> 12.5)
(Ridge,12.5)
List(Ridge, Falls)
16.5
Set(Ridge)
Source: Scala 3 Book: Maps and Collections 2.13: Maps
Nested maps are read with get and flatMap, so that a missing key at any level gives None instead of an exception.
view.filterKeys(...) is the lazy, view-based form of key filtering, described on
Views, Iterators & LazyList.
Mutable Map
A mutable.Map adds update (m(k) = v), += for a pair, put and remove (which return the previous value as an Option),
getOrElseUpdate, and in-place bulk operations.
//> using scala 3.10.0
package trailhead
import scala.collection.mutable
@main def mutableMaps(): Unit =
val m = mutable.Map("a" -> 1)
m("b") = 2
m += ("c" -> 3)
m.update("d", 4)
println(m)
println(m.put("a", 10))
println(m.put("z", 0))
println(m.remove("z"))
println(m.remove("zz"))
println(m.getOrElseUpdate("e", 5))
println(m.getOrElseUpdate("e", 6))
m.mapValuesInPlace((_, v) => v * 2)
println(m.toSeq.sortBy(_._1))
m.filterInPlace((k, _) => k != "a")
println(m.keys.toList.sorted)
m.updateWith("b")(_.map(_ + 1))
println(m("b"))
HashMap(a -> 1, b -> 2, c -> 3, d -> 4)
Some(1)
None
Some(0)
None
5
5
List((a,20), (b,4), (c,6), (d,8), (e,10))
List(b, c, d, e)
5
getOrElseUpdate(key, default) computes the default only when the key is missing and stores it; the second call with the
same key returns the stored value without running the computation, which is why both printed 5. It is the Scala counterpart
of Java’s computeIfAbsent (and of Kotlin’s getOrPut). m(k) = v desugars to m.update(k, v). Modifying a map held in a val
is fine because the reference is constant, not the contents.
Default values
A map can be wrapped so that a missing key returns a default instead of throwing. withDefaultValue(v) returns v for every missing
key and withDefault(f) computes the default from the key. The default does not affect get and contains, which still report the
truth, and it is not stored.
//> using scala 3.10.0
package trailhead
import scala.collection.mutable
@main def defaults(): Unit =
val counts = mutable.Map.empty[Char, Int].withDefaultValue(0)
for c <- "trailhead" do counts(c) += 1
println(counts.toSeq.sortBy(_._1))
println(counts('z'))
println(counts.contains('z'))
val byLength = Map("a" -> 1).withDefault(k => k.length)
println(byLength("zzz"))
println(byLength.get("zzz"))
val zero = Map("a" -> 1).withDefaultValue(0)
println(zero("q"))
println(zero.getClass.getSimpleName)
List((a,2), (d,1), (e,1), (h,1), (i,1), (l,1), (r,1), (t,1))
0
false
3
None
0
WithDefault
The counting loop, counts(c) += 1, expands to counts(c) = counts(c) + 1, and relies on the default 0 for a new character; this
is the compact way to count in Scala and it works with a mutable.Map only. For an immutable map use updatedWith or fold:
xs.foldLeft(Map.empty[Char, Int])((m, c) => m.updated(c, m.getOrElse(c, 0) + 1)).
Ordered maps: TreeMap, ListMap, VectorMap and LinkedHashMap
By default an immutable map with more than four entries is a hash trie and iterates in an unspecified order. When order matters choose a class that defines it:
-
TreeMap(immutable or mutable): sorted by key, withrange,rangeFrom,firstKey,lastKey,minAfterandmaxBefore. -
ListMapandVectorMap(immutable): insertion order.ListMaphas linear lookup and is for tiny maps;VectorMaphas effectively constant lookup and is the one to use when you need an immutable insertion-ordered map. -
mutable.LinkedHashMap: mutable insertion order with constant time lookup.
//> using scala 3.10.0
package trailhead
import scala.collection.immutable.{ListMap, SortedMap, TreeMap, VectorMap}
import scala.collection.mutable
@main def orderedMaps(): Unit =
val tm = TreeMap("Pass" -> 8.25, "Falls" -> 4.0, "Ridge" -> 12.5)
println(tm)
println(tm.firstKey)
println(tm.lastKey)
println(tm.range("G", "Q"))
println(tm.rangeFrom("Pass"))
println(tm.minAfter("G"))
println(tm.maxBefore("G"))
println(tm.keysIteratorFrom("Pass").toList)
println(SortedMap("b" -> 1, "a" -> 2).getClass.getSimpleName)
val six = (1 to 6).map(i => s"k$i" -> i)
println(Map.from(six))
println(ListMap.from(six))
println(VectorMap.from(six))
println(mutable.LinkedHashMap.from(six))
println(Map.from(six).getClass.getSimpleName)
println(Map("a" -> 1, "b" -> 2, "c" -> 3, "d" -> 4).getClass.getSimpleName)
println(VectorMap("x" -> 1, "y" -> 2, "z" -> 3) - "y" + ("y" -> 9))
println(ListMap("x" -> 1, "y" -> 2) + ("x" -> 5))
val mm = mutable.TreeMap(3 -> "c", 1 -> "a")
mm(2) = "b"
println(mm)
val lhm = mutable.LinkedHashMap("z" -> 1, "a" -> 2)
lhm("m") = 3
println(lhm)
TreeMap(Falls -> 4.0, Pass -> 8.25, Ridge -> 12.5)
Falls
Ridge
TreeMap(Pass -> 8.25)
TreeMap(Pass -> 8.25, Ridge -> 12.5)
Some((Pass,8.25))
Some((Falls,4.0))
List(Pass, Ridge)
TreeMap
HashMap(k2 -> 2, k5 -> 5, k6 -> 6, k1 -> 1, k4 -> 4, k3 -> 3)
ListMap(k1 -> 1, k2 -> 2, k3 -> 3, k4 -> 4, k5 -> 5, k6 -> 6)
VectorMap(k1 -> 1, k2 -> 2, k3 -> 3, k4 -> 4, k5 -> 5, k6 -> 6)
LinkedHashMap(k1 -> 1, k2 -> 2, k3 -> 3, k4 -> 4, k5 -> 5, k6 -> 6)
HashMap
Map4
VectorMap(x -> 1, z -> 3, y -> 9)
ListMap(x -> 5, y -> 2)
TreeMap(1 -> a, 2 -> b, 3 -> c)
LinkedHashMap(z -> 1, a -> 2, m -> 3)
Note in the output that Map.from(six) (six entries) is a HashMap with scrambled order, while ListMap, VectorMap and
LinkedHashMap keep the order k1 to k6; and that Map with four entries is the specialised class Map4. Updating a key
that already exists in a ListMap keeps its original position (x -> 5 still first), and re-adding a removed key to a
VectorMap puts it at the end.
Concurrent maps
A scala.collection.concurrent.Map is a mutable map whose operations are atomic: putIfAbsent, remove(key, value),
replace(key, value) and getOrElseUpdate. The standard implementation is TrieMap, a lock-free hash trie with constant time
snapshots; Java’s ConcurrentHashMap is available as the same interface through asScala.
//> using scala 3.10.0
package trailhead
import java.util.concurrent.ConcurrentHashMap
import scala.collection.concurrent.TrieMap
import scala.jdk.CollectionConverters.*
@main def concurrentMaps(): Unit =
val tr = TrieMap("a" -> 1)
tr.put("b", 2)
println(tr.putIfAbsent("a", 99))
println(tr.putIfAbsent("c", 3))
println(tr.replace("a", 10))
println(tr.remove("b", 2))
println(tr.getOrElseUpdate("d", 4))
println(tr.toSeq.sortBy(_._1))
println(tr.readOnlySnapshot().size)
println(tr.getClass.getName)
val chm = ConcurrentHashMap[String, Int]()
val m = chm.asScala
m.put("a", 1)
println(m.putIfAbsent("a", 2))
println(m.getOrElseUpdate("b", 5))
println(chm.get("b"))
println(m.getClass.getName)
println(m.updateWith("a")(_.map(_ + 1)))
println(m.toSeq.sortBy(_._1))
Some(1)
None
Some(1)
true
4
List((a,10), (c,3), (d,4))
3
scala.collection.concurrent.TrieMap
Some(1)
5
5
scala.collection.convert.JavaCollectionWrappers$JConcurrentMapWrapper
Some(2)
List((a,2), (b,5))
putIfAbsent returns the existing value (Some(1)) or None when it inserted; remove(key, value) and replace(key, value)
are conditional and return a Boolean or the previous value. readOnlySnapshot() is an immutable view taken in constant time.
Plain mutable.HashMap and mutable.HashSet are not thread safe; use a concurrent map, an immutable map in an atomic
reference, or confine the map to one thread. See also Parallel Collections & Concurrency Libraries,
and for a Java thread-safety comparison the Java page on Virtual Threads.
Mutable versus immutable at the boundary
A mutable map is an scala.collection.Map but not an immutable.Map, and the compiler distinguishes the two Map traits in its
error message by adding a superscript to the name; val m = Map(...) followed by m("b") = 2 fails because only the mutable
map has update:
//> using scala 3.10.0
import scala.collection.mutable
@main def bad(): Unit =
val m = Map("a" -> 1)
m("b") = 2
val mm = mutable.Map(1 -> "a")
val i: Map[Int, String] = mm
-- [E008] Not Found Error: mapbad.scala:6:2
6 | m("b") = 2
| ^
|value update is not a member of Map[String, Int] - did you mean m.updated?
-- [E007] Type Mismatch Error: mapbad.scala:8:28
8 | val i: Map[Int, String] = mm
| ^^
| Found: (mm : scala.collection.mutable.Map[Int, String])
| Required: Map²[Int, String]
|
| where: Map is a trait in package scala.collection.mutable
| Map² is a trait in package scala.collection.immutable
|
| longer explanation available when compiling with `-explain`
2 errors found
Compilation failed
Expose a mutable map through the read-only type scala.collection.Map when callers should not change it, and know that this is
a view, not a copy: later changes through the owner are visible. For a frozen copy call toMap:
//> using scala 3.10.0
package trailhead
import scala.collection.mutable
@main def sharing(): Unit =
val shared = mutable.Map("a" -> 1)
val readOnly: scala.collection.Map[String, Int] = shared
shared("b") = 2
println(readOnly)
val snapshot = shared.toMap
shared("c") = 3
println(snapshot)
HashMap(a -> 1, b -> 2)
Map(a -> 1, b -> 2)
Comparison with Java and Kotlin
| Aspect | Scala | Java | Kotlin |
|---|---|---|---|
Default map |
Immutable |
|
|
Iteration order |
Unspecified for |
Unspecified for |
Insertion order by default. |
Sorted |
|
|
|
Missing key |
|
|
|
Get or create |
|
|
|
Atomic update |
|
|
|
Sets |
|
|
|
Null keys and values |
Allowed in |
|
Nullable keys need a nullable type; see Kotlin Null Safety. |
For the Option-based style, see Optional and Option & Null Safety. Passing maps and sets across the Scala-Java boundary uses the converters in Collections Overview.
Common pitfalls
-
Relying on
SetorMapiteration order when there are more than four entries. UseVectorMapor aTreeMap. -
m(key)on a missing key throws. Useget,getOrElseor a default map. -
Deprecated
mapValues.m.mapValues(f)returns a lazy view that recomputesfon every access and is deprecated since 2.13.0 ("Use .view.mapValues(f). A future version will include a strict version of this method"); writem.view.mapValues(f).toMapfor a strict map, orm.map((k, v) => k -> f(v)). The same applies tofilterKeys, with.view.filterKeys(p).toMap. -
A literal with duplicate keys keeps the last one, silently:
Map("a" -> 1, "a" -> 2)isMap(a -> 2). -
Mapping a
Setmerges results:Set(1, 2, 3).map(_ % 2)isSet(1, 0), not three elements. Convert to aListfirst when you want to keep duplicates. -
Mutating the default of
withDefault. The default is not stored;counts(c)for a missing key returns0but does not add the key. -
Forgetting thread safety. Non-concurrent mutable maps and sets corrupt under concurrent writes.
-
Using a
ListMapfor large data: lookup is linear. UseVectorMap. -
Comparing a
Setwith aListis rejected by the compiler (E172), see Collections Overview.
Here is the deprecation in action, with the strict replacement and a map with a duplicate literal key:
//> using scala 3.10.0
package trailhead
@main def mapDeprecated(): Unit =
val m = Map("a" -> 1)
println(m.mapValues(_ + 1).toMap)
println(m.view.mapValues(_ + 1).getClass.getSimpleName)
val dup: Map[String, Int] = Map("a" -> 1, "a" -> 2)
println(dup)
for (k, v) <- m do println(s"$k=$v")
println(m.map((k, v) => (k.length, v)))
println(m.map((k, v) => k))
println(m.groupBy(_._2 % 2))
Map(a -> 2)
MapValues
Map(a -> 2)
a=1
Map(1 -> 1)
List(a)
HashMap(1 -> Map(a -> 1))
-- Deprecation Warning: mapdep.scala:6:12
6 | println(m.mapValues(_ + 1).toMap)
| ^^^^^^^^^^^
|method mapValues in trait MapOps is deprecated since 2.13.0: Use .view.mapValues(f). A future version will include a strict version of this method (for now, .view.mapValues(f).toMap).
1 warning found
Where the books are outdated
-
mapValuesandfilterKeysonMapreturned lazy views and were fine in 2.12 material; they are deprecated since 2.13.0. -
Scala 2 code must write
case (k, v) =>in lambdas over pairs; Scala 3 lets you write(k, v) =>directly. -
scala.collection.JavaConverters(andJavaConversions) appear in material aboutConcurrentHashMapand Java maps; usescala.jdk.CollectionConverters(asScala) as shown above. -
The
+method on a map that takes several pairs,m + (a -> 1, b -> 2), is deprecated since 2.13.0: the compiler asks for++with an explicit collection argument instead; writem ++ Map(a -> 1, b -> 2).
Scala 3.9 LTS versus 3.10
The set and map classes, their operations and the compiler messages shown on this page are identical on 3.3.8, 3.9.0 and
3.10.0: every program was compiled and run on all three and produced the same output, including the E007 and E008 errors and
the mapValues deprecation. Nothing in the sets and maps part of the library is gated behind a newer Scala 3 release.