Luet oppimateriaalin englanninkielistä versiota. Mainitsit kuitenkin taustakyselyssä
osaavasi suomea. Siksi suosittelemme, että käytät suomenkielistä versiota, joka on
testatumpi ja hieman laajempi ja muutenkin mukava.
Suomenkielinen materiaali kyllä esittelee englanninkielisetkin termit.
Kieli vaihtuu A+:n sivujen yläreunan painikkeesta. Tai tästä: Vaihda suomeksi.
About This Page
Questions Answered: How do I store information that consists of
multiple related elements? How can I refer to such a collection of
elements from multiple locations within a program?
Topics: The basics of using collections in general and buffers in
What Will I Do? Program in the REPL and read.
Rough Estimate of Workload:? About an hour.
Points Available: A20.
Related Modules: None.
Most computer programs manipulate many granules of information that are related to
each other in some way. For instance, a program might need to keep track of multiple
scientific measurements, multiple hotel experiences recorded by the user, multiple
friends of the user, or multiple students enrolled in a course.
For such purposes, we use collections (kokoelma). A collection may contain,
for instance, all the friends of a particular user, or a sequence of measurements.
A value stored in a collection is called an element (alkio) of the collection.
An element could be a single measurement, a single experience, or a single person,
There are different kinds of collections. Since the need for collections is so universal,
programming languages provide a selection of collection types for the programmer to pick
and choose from. Scala offers a plentiful selection, but initially we’ll use just one type
of collection known as a buffer (puskuri).
In Scala, a buffer is a collection that stores its elements in a specific order. You
can add new elements to a buffer, remove elements that were previously added, or replace
elements with new ones. Informally, you can think of a buffer as a sort of editable list
of items stored in computer memory.
To get started, let’s try creating a buffer that contains four strings as its elements:
Buffer("the first element", "second", "third", "and a fourth")res0: scala.collection.mutable.Buffer[String] = ArrayBuffer(the first element, second, third, and a fourth)
Two more examples of buffer creation are shown below. We have a buffer with two String
elements and another with five Doubles.
Buffer("ABC", "XYZ")res1: scala.collection.mutable.Buffer[String] = ArrayBuffer(ABC, XYZ)
Buffer(2.40, 3.11, 4.56, 10.29, 8.11)res2: scala.collection.mutable.Buffer[Double] = ArrayBuffer(2.4, 3.11, 4.56, 10.29, 8.11)
Each of a buffer’s elements is stored at a particular location within the buffer; each
such location is identified by its running number, called an index (indeksi). When
we manipulate buffers, we often use indices to target specific elements.
Let’s try examining, modifying, and adding elements. To begin with, here’s an example
of a variable that refers to a buffer. This variable will be useful for accessing the
collection after it’s been created.
val numbers = Buffer(12, 2, 4, 7, 4, 4, 10, 3)numbers: Buffer[Int] = ArrayBuffer(12, 2, 4, 7, 4, 4, 10, 3)
Here’s how you can access the value stored at a particular index. First indicate the
buffer that you wish to examine, then put the desired index in round brackets:
numbers(0)res3: Int = 12
Indices start from zero! The above expression accesses the buffer’s first element.
You can use expressions like the one above in many ways. For instance, you can access
a buffer element and assign that value to a variable. In the example below, the buffer’s
fourth element (that is, the value at index three) is assigned to the variable fourthNumber:
val fourthNumber = numbers(3)fourthNumber: Int = 7
You can replace an element with a new value by adding an equals sign. In this example,
the fourth element in the buffer is replaced by the number one:
numbers(3) = 1
That command does not in itself produce any value of interest. It just instructs the
computer to modify the buffer’s contents and doesn’t evaluate to a value in itself.
This is why the REPL stays silent. However, we can request the value of the variable
and see that the fourth element has indeed changed in the computer’s memory:
numbersres4: Buffer[Int] = ArrayBuffer(12, 2, 4, 1, 4, 4, 10, 3)
That change affected only the buffer, not the variable that we used earlier to store the
fourthNumberres5: Int = 7
The operator += adds a new element at the end of the buffer. This means that the
buffer’s size goes up.
numbers += 11res6: Buffer[Int] = ArrayBuffer(12, 2, 4, 1, 4, 4, 10, 3, 11)
Using a buffer is very similar to using a variable, with the addition that we need
indices to target specific elements. In a sense, a buffer is like a numbered list of
Speaking of which: The variable that we used to refer to the buffer is a val. It
being a val doesn’t prevent us from modifying the buffer’s contents; val is not
an attribute of the buffer itself. If numbers the variable is defined as a val,
then that variable cannot be reassigned so that it would later refer to some other
buffer. Nevertheless, it is possible to change the contents of the buffer that numbers
It’s often useful to create a buffer that contains no elements yet. For instance, when
the GoodStuff application launches, there are initially no recorded experiences even
though experiences may be added later.
The following doesn’t quite accomplish what we want:
val wonderIfThisWorks = Buffer()wonderIfThisWorks: Buffer[Nothing] = ArrayBuffer()
That command did make us a new empty buffer, but empty it will remain. The computer
doesn’t know what we’re planning to store in the buffer, and the Scala toolkit determines
the buffer’s type to be Buffer[Nothing]. Such a buffer won’t bring us any joy, since we
can’t add anything to it.
We can, however, tell the computer what kind of buffer we want to create. Let’s try
creating an empty buffer that can be subsequently used store strings. The type parameter —
String in this case — goes in square brackets just like you already saw in REPL outputs:
val words = Buffer[String]()words: Buffer[String] = ArrayBuffer()
We can now add strings to this buffer:
words += "llama"res7: Buffer[String] = ArrayBuffer(llama)
Actually, you’re allowed to type in the type parameter whenever you create a buffer, even
where it’s not necessary. This works, too:
val numbers = Buffer[Int](2, -1, 10)numbers: Buffer[Int] = ArrayBuffer(2, -1, 10)
We could have omitted the type parameter [Int] because the
Scala toolkit figures out that we want a Buffer[Int] from the
expressions 2, -1, and 10, which determine the buffer’s
The questions below should help you build an understanding of the basic buffer
commands. Work out what the given code fragments do. Experiment in the REPL.
Examine the following commands. What do they do to the buffer?
val testBuffer = Buffer(4, 10, 3, 10, 15, -2)
val someIndex = 4
val chosenValue = testBuffer(2)
println(chosenValue + testBuffer(someIndex) + testBuffer(4))
Please enter the number printed out by the last command:
The following example adds elements to a buffer. What happens
to the buffer at each step?
val words = Buffer[String]()
val word = "love"
words += "ents"
words += word
words += "elem" + words(0)
println(words(0) + " " + words(1) + " " + words(2))
Please enter the text printed out by the last line:
val testBuffer = Buffer(4, 10, 3, 10, 15, -2)
var index = 0
testBuffer(index) = 0
index = index + 1
testBuffer(index) = 0
index = index + 1
testBuffer(index) = 0
index = index + 1
testBuffer(index) = 0
After executing these commands, what is the sum of the elements in the buffer?
Let’s assume the following lines of code have just been executed.
val numbers = Buffer(10.5, 10.3, 9.8, 7.9, 10.2, 9.7)
val numberOfElements = 6
val empty = Buffer[Double]()
Below are a few attempts to access an individual element of the buffer. Which of them
result in an error message (and why)?
Chapter 1.4 said that a variable stores just a single value. But didn’t we just have a
buffer variable that contained multiple values?
Sort of, but not really.
As we take a look at this question, you’ll get to know the concept of reference
(viittaus). Eventually, it will turn out that this concept has a significance in
programming that extends well beyond buffers.
Did you notice that test is the name of a variable, not the name of a buffer? (Buffers
don’t have names.) This fact will be important momentarily.
References have a concrete impact on how programs work. Take a look at another animation.
Think through the following code and answer the questions. If this
assignment seems challenging, you may find that it helps to draw a diagram
of the buffers, variables, and references involved. You can also enter the
code in the REPL. If you struggle to make progress, review the material
on buffers and references above or ask for help.
var person = Buffer("Sauli")
var another = Buffer("Sauli")
var presidentOfFinland = another
How many buffers does this code create?
Let’s continue by executing the following lines next.
presidentOfFinland += "Väinämö"
another += "Niinistö"
How many buffers exist now?
Next, let’s execute this command:
another = Buffer("Jenni", "Haukio")
How many elements are there now in the buffer that the variable presidentOfFinland refers to?
another = person
person = Buffer("Lennu")
How many of the variables now refers to a buffer that contains the names "Jenni"
There is a myriad of things that you can do with buffers and other kinds of collections.
We have hardly scratched the surface. You’ll see many examples of collections in the
chapters that follow; as we already suggested, the experience categories in the GoodStuff
application will be one such example. We’ll be storing many different kinds of values in
collections, not just individual numbers or strings.
Right now, what matters most is that you know how to create buffers and how to access
and modify their individual elements. And that you know that you manipulate buffers via
You can expect the concept of reference to come up time and again. We’ll use references
to point at many other things than buffers, too.
Beginners often find references a hard concept to grasp. One of the reasons is language.
When we humans talk or write about programming, we often take “shortcuts”. It’s rare for
us to say that “the variable numbers contains a reference to a buffer”; instead, we
often say “the variable numbers contains a buffer” or something similarly imprecise.
We may also speak of a “numbers buffer” even though the variable really contains only
a reference and numbers is the name of a variable, not of a buffer. (As you’ve seen,
multiple differently named variables can store a reference to the same buffer.) Speaking
simply and imprecisely is natural and convenient, and we don’t need to strictly avoid it,
but if we are to write programs that work, we do need to understand what the words really
Psst! As a matter of fact...
... to be precise, the values of many standard Scala data types —
including Strings — are “at the ends of references” just
like you’ve seen buffers to be. We didn’t bring this up before,
and the animated diagrams in this ebook generally don’t display
references when it comes to certain common data types. But here’s
one animation that is more “truthful” (detailed) than the earlier
animations that featured strings, even if that truthfulness makes
the animation a bit more cumbersome:
Generally, it’s more convenient to think in simplified terms.
For example, we may think of the string “cat” itself as being
stored in a variable (as in earlier animations) rather than the
variable referring to another memory location that contains the
string (as above). We’ll continue use the simplified representation
in later animations.
The above simplification is “safe” for the String data type
and won’t lead us to reason erroneously about program behavior
because — unlike a buffer — a string value never changes
internally. Even when we combine a string with another, like in
the preceding example, we don’t modify the existing strings but
create a new string. That’s something we’ll return to in
Chapters 5.2 and 10.2.
An updated concept map:
Please note that this section must be completed individually.
Even if you worked on this chapter with a pair, each of you should submit the form separately.
Time spent: (*) Required
Please estimate the total number of minutes you spent on this chapter (reading, assignments,
etc.). You don’t have to be exact, but if you can produce an estimate to within 15 minutes or
half an hour, that would be great.
Written comment or question:
You aren’t required to give written feedback. Nevertheless, please
do ask something, give feedback, or reflect on your learning!
(However, the right place to ask urgent questions about programs
that you’re currently working on isn’t this form but the lab sessions
or Piazza. We can’t guarantee that anyone will even see anything
you type here before the weekly deadline.)
Thousands of students have given feedback that has contributed to this ebook’s design.
The ebook’s chapters, programming assignments, and weekly bulletins have been written in
Finnish and translated into English by Juha Sorva.
The appendices (glossary, Scala reference,
FAQ, etc.) are by Juha Sorva unless otherwise specified on the page.
The automatic assessment of the assignments has been developed by: (in alphabetical order)
Riku Autio, Nikolas Drosdek, Joonatan Honkamaa, Jaakko Kantojärvi, Niklas Kröger, Teemu
Lehtinen, Strasdosky Otewa, Timi Seppälä, Teemu Sirkiä, and Aleksi Vartiainen.
The illustrations at the top of each chapter, and the similar drawings elsewhere in the
ebook, are the work of Christina Lassheikki.
The animations that detail the execution Scala programs have been designed by Juha
Sorva and Teemu Sirkiä. Teemu Sirkiä and Riku Autio did the technical implementation,
relying on Teemu’s Jsvee and Kelmu toolkits.
The other diagrams and interactive presentations in the ebook are by Juha Sorva.
The O1Library software
has been developed by Aleksi Lukkarinen and Juha Sorva. Several of its key components
are built upon Aleksi’s SMCL
The pedagogy of using O1Library for simple graphical programming (such as Pic) is
inspired by the textbooks How to Design Programs by Flatt, Felleisen, Findler, and
Krishnamurthi and Picturing Programs by Stephen Bloch.
The course platform A+ was originally created at Aalto’s LeTech
research group as a student project. The open-source project
is now shepherded by the Computer Science department’s edu-tech team and hosted by the department’s IT
Markku Riekkinen is the current lead developer; dozens of Aalto students and others have also contributed.
The A+ Courses plugin,
which supports A+ and O1 in IntelliJ IDEA, is another open-source project. It was created by Nikolai
Denissov, Olli Kiljunen, Nikolas Drosdek, Styliani Tsovou, Jaakko Närhi, and
Paweł Stróżański with input from Juha Sorva, Otto Seppälä, Arto Hellas, and others.
For O1’s current teaching staff, please see Chapter 1.1.
Additional credits appear at the ends of some chapters.