List
In Scala, a List
is immutable. After we create a List
, we can modify the elements when creating a new List
. With functions we process many elements at once.
Lists have many helpful properties—we can access the first element, last element, or length. No custom code is needed for these things.
Let's get started with Lists. Here we create a List
of animal names—it has three strings in it. We use val
to indicate the "names" variable is constant, a value.
Length
returns the number of elements in the list (its size). The size property is the same as length.object Program { def main(args: Array[String]): Unit = { // Create a String List with 3 elements. val names = List("cat", "bird", "fish") // Print the list. println(names) // Print element count (the list size). println(names.length) // Access the first and then last elements. val first = names(0) println(first) val last = names(names.length - 1) println(last) } }List(cat, bird, fish) 3 cat fish
Head
, tailWith head we access the first element in a List
. In this example this returns a String
. And tail returns a new List
of all elements excluding the head (so elements 2 on).
object Program { def main(args: Array[String]): Unit = { val ids = List("Antarctica", "Asia", "Africa") println(ids) // The head is the first element in the list. val head = ids.head println(head) // The tail is a list of all elements except the first. println(ids.tail) println(ids.tail.length) } }List(Antarctica, Asia, Africa) Antarctica List(Asia, Africa) 2
With map, we apply a function to each element in a List
. A new List
is created with the results of those function calls. The lambda expression uses "_" as the argument.
map()
on a string
List
. We call toUpperCase()
on all elements, and the resulting List
has uppercased color names.object Program { def main(args: Array[String]): Unit = { // A list of strings. val colors = List("blue", "yellow", "green") // Use map to uppercase all strings in the list. // ... The underscore is each variable encountered. val result = colors.map(_.toUpperCase()) println(result) } }List(BLUE, YELLOW, GREEN)
With the "++" operator, we combine two Lists. A new List
is created, and the left side comes before the elements in the right side.
object Program { def main(args: Array[String]): Unit = { // Create two String lists. val positions1 = List("top", "bottom") val positions2 = List("left", "right") println(positions1) println(positions2) // Combine the two lists with an operator. val positions3 = positions1 ++ positions2 println(positions3) } }List(top, bottom) List(left, right) List(top, bottom, left, right)
To use slice()
we must provide two indexes: the start index and an "until" index (an end-index that is not included in the slice). Slice does not use a count of elements.
List
of ids with indexes 0 through 4 inclusive. We take slices of this List
.object Program { def main(args: Array[String]): Unit = { val ids = List(20, 21, 22, 23, 24) // indexes: // 0 = 20 // 1 = 21 // 2 = 22 // 3 = 23 // 4 = 24 // Take slice from index 2 until 4 (excludes 4). val result1 = ids.slice(2, 4) println(result1) // Take slice from index 0 until 3. val result2 = ids.slice(0, 3) println(result2) } }List(22, 23) List(20, 21, 22)
SplitAt
This method divides a List
into two parts. We specify the index at which we want the split to occur. A tuple (containing two Lists) is returned.
splitAt
. This syntax form makes it easy to use the two resulting Lists.object Program { def main(args: Array[String]): Unit = { // This list contains four Booleans. val list = List(true, false, true, true) // Split this list at index 2 (before the third element). // ... This returns a tuple containing two lists. val (left, right) = list.splitAt(2) // Print results of splitAt. println(left) println(right) } }List(true, false) List(true, true)
With "::" we add an element to the beginning of a List
. We combine an element with an existing List
. To combine two Lists, another operator (with two pluses) can be used.
object Program { def main(args: Array[String]): Unit = { val verbs1 = List("open", "search", "close", "sort") // Add a string to the list's start. val verbs2 = "mix" :: verbs1 // Print our lists. println(verbs1) println(verbs2) } }List(open, search, close, sort) List(mix, open, search, close, sort)
This is a function on lists. With foreach()
we call a function (usually specified as a lambda expression) on each element. No return value is used.
string
in a List
.object Program { def main(args: Array[String]): Unit = { // A list of four nouns (strings). val nouns = List("computer", "box", "table", "wall") // Call a lambda function on each element with foreach. // ... Write uppercase strings to the screen. nouns.foreach(x => println(x.toUpperCase())) } }COMPUTER BOX TABLE WALL
We will get a "value update" error if we try to change an element in a List
. In Scala, Lists are read-only—this makes copying fast, but updating impossible.
object Program { def main(args: Array[String]): Unit = { val names = List("cat", "bird", "dog") // A list cannot be updated. // ... This will not compile. names(0) = "fish" } }error: value update is not a member of List[String] names(0) = "fish" ^ one error found
val
In Scala we can use var
and val
to reference Lists. Please note that Lists are always immutable. But with var
, we can reassign the list variable to a different object.
List
. But then we can rebind it to another, separate List
.object Program { def main(args: Array[String]): Unit = { // Create a variable list. var things = List(10, 11, 15) println(things) // Change the variable binding. things = List(16, 19, 200) println(things) } }List(10, 11, 15) List(16, 19, 200)
val
, continuedWith val
, we cannot rebind to another object. A "reassignment to val
" compile-time error will occur. With var
, this program would compile.
List
object itself is always unchangeable. But with var
we can point to different Lists with one variable.object Program { def main(args: Array[String]): Unit = { val x = List(1.5, 2.5, 10.1) // This will not compile. // ... A val cannot be bound to a new object. x = List(2.1, 2.5) } }error: reassignment to val x = List(2.1, 2.5) ^ one error found
Here we have two local variables. We create a List
based on the values of those variables. When we reassign one, its new value is not reflected in the List
.
List
is frozen at creation-time. It is not changed, even when the var
is reassigned. It contains values, not references.List
, even when created based on variable data, is immutable. It is frozen in time once we create it.object Program { def main(args: Array[String]): Unit = { // Two string variables. var shape1 = "BOX" var shape2 = "SPHERE" // Create immutable list with variables in it. val shapes = List(shape1, shape2) // Change the variable. // ... The value change is not reflected in the list. shape1 = "CUBE" println(shape1) println(shape2) println(shapes) } }CUBE SPHERE List(BOX, SPHERE)
Often we pass a List
as an argument to a function. Here we introduce a function that receives a List
of Ints. We pass a List
instance to this function and print its result.
object Program { def main(args: Array[String]): Unit = { // Receives a List argument. def lengthDoubled(values: List[Int]) = values.length * 2 // Pass list to def as argument. val shades = List(10, 0, 5) val result = lengthDoubled(shades) println(result) } }6
Find
This method receives a lambda expression and returns the first matching result in an option. We can use getOrElse
to test the option returned by find()
.
object Program { def main(args: Array[String]): Unit = { // A List with 3 items. val languages = List("python", "scala", "java") // Find an element that starts with this letter. val result = languages.find { x => x.charAt(0) == 's' } println(result.getOrElse("No s")) // No items are found starting with this letter. val result2 = languages.find(_.charAt(0) == 'z') println(result2.getOrElse("No z")) } }scala No z
In Scala a List
is immutable. It must be copied each time we want to modify something. This makes some operations (like appending) slower.
List
, we can just reuse an existing List
, as Lists will never change.A List
can store important elements in a program. Elements within the List
are ordered one after another and are countable. In functional designs we can change and test Lists.