List ExamplesUse List to store Strings and Ints together. Access length and use the for-loop.
This page was last reviewed on Nov 5, 2021.
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.
Shows a listShows a listShows a map
List details. Lists have many helpful properties—we can access the first element, last element, or length. No custom code is needed for these things.
Initialize List
2D List
First example. Let's get started with Lists. Here we create a list of animal names. It has 3 strings in it. We use val to indicate the "names" variable is constant, a value.
Detail This property returns the number of elements in the list (its size). The "size" property is the same as length.
Detail To access the first element, we use index zero. And for the last one, we use the list's length minus 1.
Shows a list
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, tail. With 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).
Shows a list
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
Map function. 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.
Here We call map() on a string list. We call toUpperCase() on all elements, and the resulting list has uppercased color names.
Shows a map
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) } }
Combine lists. With "++" 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)
Slice. 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.
Here We provide a 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.
Tip We unpack our tuple immediately after calling 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)
Add to start. 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)
Foreach. 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.
Here We have a lambda that uppercases, and then prints, each 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())) } }
Update error. 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
Var versus 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.
Detail We use the "things" variable and bind it to one List. But then we can rebind it to another, separate list.
var, val
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)
Var versus val, continued. With val, we cannot rebind to another object. A "reassignment to val" compile-time error will occur. With var, this program would compile.
Thus A 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
Var reassignment, list. 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.
Detail The list is frozen at creation-time. It is not changed, even when the var is reassigned. It contains values, not references.
Detail A 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) } }
Argument. 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) } }
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
IndexOf. This method is used to locate an element within a List. And with indexOfSlice, we can try to find an entire series of elements within a List.
List versus Vector. In my testing, a Vector is slower than a List for small element counts. The Vector is an immutable collection similar to a list.
Remove duplicates. With the distinct function on the List type we can eliminate duplicate elements from a list. Other approaches, like using toSet, are also possible.
Notes, immutable. In Scala a List is immutable. It must be copied each time we want to modify something. This makes some operations (like appending) slower.
But Immutability has many advantages. To copy a list, can just reuse an existing list, as it will never change.
And There are known security benefits to immutable objects. Threads (which become increasingly important in our world) also benefit.
A summary. Lists often contain the most important parts of programs. Elements, like trees in a forest, are countable. In functional designs we can change and test lists.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on Nov 5, 2021 (edit link).
© 2007-2023 Sam Allen.