This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 11.3, “How to Add Elements to a List in Scala”
Problem
You want to add elements to a List
that you’re working with.
Solution
“How do I add elements to a List?” is a bit of a trick question, because a List
is immutable, so you can’t actually add elements to it. If you want a List
that is constantly changing, use a ListBuffer
(as described in Recipe 11.2), and then convert it to a List
when necessary.
To work with a List
, the general approach is to prepend items to the list with the ::
method while assigning the results to a new List
:
scala> val x = List(2) x: List[Int] = List(2) scala> val y = 1 :: x y: List[Int] = List(1, 2) scala> val z = 0 :: y z: List[Int] = List(0, 1, 2)
Rather than continually reassigning the result of this operation to a new variable, you can declare your variable as a var
, and reassign the result to it:
scala> var x = List(2) x: List[Int] = List(2) scala> x = 1 :: x x: List[Int] = List(1, 2) scala> x = 0 :: x x: List[Int] = List(0, 1, 2)
As these examples illustrate, the ::
method is right-associative; lists are constructed from right to left, which you can see in this example:
scala> val list1 = 3 :: Nil list1: List[Int] = List(3) scala> val list2 = 2 :: list1 list2: List[Int] = List(2, 3) scala> val list3 = 1 :: list2 list3: List[Int] = List(1, 2, 3)
Any Scala method that ends with a :
character is evaluated from right to left. This means that the method is invoked on the right operand. You can see how this works by analyzing the following code, where both methods print the number 42
:
object RightAssociativeExample extends App { val f1 = new Printer f1 >> 42 42 >>: f1 } class Printer { def >>(i: Int) { println(s"$i") } def >>:(i: Int) { println(s"$i") } }
The two methods can also be invoked like this:
f1.>>(42) f1.>>:(42)
but by defining the second method to end in a colon, it can be used as a right-associative operator.
Though using ::
is very common, there are additional methods that let you prepend or append single elements to a List:
scala> val x = List(1) x: List[Int] = List(1) scala> val y = 0 +: x y: List[Int] = List(0, 1) scala> val y = x :+ 2 y: List[Int] = List(1, 2)
You can also merge lists to create a new list. See Recipe 11.5 for examples.
Discussion
If you’re not comfortable using a List
, but want to use a mutable, linear list, see Recipe 11.2, “Creating a Mutable List” for examples of how to use the ListBuffer
class.
The ListBuffer
is a mutable, linear sequence (as opposed to an indexed sequence, like an Array
or ArrayBuffer
), and is similar to working with a StringBuffer
or StringBuilder
in Java. Just as you’d convert those classes to a String
when needed, you convert a ListBuffer
to a List
when needed. Programmers from other backgrounds may be more comfortable with the ::
approach. A nice benefit of Scala is that it offers both options.
See Also
- Recipe 11.2, “Creating a Mutable List”
- Recipe 10.4, “Understanding the Performance of Collections”
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |