Table of Contents
- ArrayBuffer introduction
- Notes about the following ArrayBuffer examples
- Import it
- CREATE: How to create an initial, empty ArrayBuffer
- CREATE: How to create a new ArrayBuffer with initial elements
- CREATE: Create a new ArrayBuffer by populating it
- READ: How to access ArrayBuffer elements
- UPDATE: Append, prepend, insert, and clear
- UPDATE: ArrayBuffer “in place” methods
- DELETE: Removing elements from an ArrayBuffer
- MORE: Using functional methods with ArrayBuffer
- Scala ArrayBuffer summary
Summary: This page contains a large collection of examples of how to use the Scala ArrayBuffer class.
ArrayBuffer introduction
Use the ArrayBuffer
class when you want to use a general-purpose, mutable indexed sequence in your Scala applications:
- Mutable: you can change the elements in the collection, and resize the collection
- Indexed: random access of elements is very fast; this means you can access elements quickly by their element number, such as
people(12345432)
(a linked list would be very slow for this purpose)
Just as the Vector class is the recommended “go to” class for immutable, indexed sequential collections, the ArrayBuffer
class is recommended as the general-purpose collections class for mutable, indexed sequential collections.
ArrayBuffer
is an indexed sequential collection. UseListBuffer
if you prefer a linear sequential collection that is mutable.
Notes about the following ArrayBuffer examples
The following examples are demonstrated in what I call a “CRUD+” order, meaning that the methods are shown in this order:
- C — Create
- R — Read
- U — Update
- D — Delete
- + — demonstrates many methods available on the
ArrayBuffer
class
Import it
To use an ArrayBuffer
you need to import it into the scope of your application:
import scala.collection.mutable.ArrayBuffer
In Scala, immutable collections are preferred, so when you want to use a mutable collection like ArrayBuffer
, you need to import it first.
CREATE: How to create an initial, empty ArrayBuffer
Here are a few examples of how to create a new, empty ArrayBuffer
:
val fruits = ArrayBuffer[String]()
val ints = ArrayBuffer[Int]()
val people = ArrayBuffer[Person]()
If you know your ArrayBuffer
will need to hold a lot of elements you can create it with an initial size:
// ready to hold 100,000 ints
val buf = new ArrayBuffer[Int](100_000)
CREATE: How to create a new ArrayBuffer with initial elements
To create a new ArrayBuffer
with initial elements, just specify the elements to add, like this:
val nums = ArrayBuffer(1, 2, 3)
val people = ArrayBuffer(
Person("Al"),
Person("Kim"),
Person("Jim")
)
CREATE: Create a new ArrayBuffer by populating it
You can also create a new ArrayBuffer
that’s populated with initial elements using a Range
:
// to, until
(1 to 5).toBuffer // ArrayBuffer(1, 2, 3, 4, 5)
(1 until 5).toBuffer // ArrayBuffer(1, 2, 3, 4)
(1 to 10 by 2).toBuffer // ArrayBuffer(1, 3, 5, 7, 9)
(1 until 10 by 2).toBuffer // ArrayBuffer(1, 3, 5, 7, 9)
(1 to 10).by(2).toBuffer // ArrayBuffer(1, 3, 5, 7, 9)
('d' to 'h').toBuffer // ArrayBuffer(d, e, f, g, h)
('d' until 'h').toBuffer // ArrayBuffer(d, e, f, g)
('a' to 'f').by(2).toBuffer // ArrayBuffer(a, c, e)
// range method
ArrayBuffer.range(1, 3) // ArrayBuffer(1, 2)
ArrayBuffer.range(1, 6, 2) // ArrayBuffer(1, 3, 5)
You can also use the fill
and tabulate
methods:
ArrayBuffer.fill(3)("foo") // ArrayBuffer(foo, foo, foo)
ArrayBuffer.tabulate(3)(n => n * n) // ArrayBuffer(0, 1, 4)
ArrayBuffer.tabulate(4)(n => n * n) // ArrayBuffer(0, 1, 4, 9)
fill
is a nice way to populate an ArrayBuffer
with random data:
val r = scala.util.Random
ArrayBuffer.fill(5)(r.nextInt(10)) // ArrayBuffer(4, 4, 3, 9, 1)
ArrayBuffer.fill(5)(r.nextPrintableChar) // ArrayBuffer(|, ], U, X, l)
If you have a populated ArrayBuffer
you can also modify the values of each element in place with transform
:
val a = ArrayBuffer.range(1,5) // ArrayBuffer(1, 2, 3, 4)
a.transform(_ * 2) // a = ArrayBuffer(2, 4, 6, 8)
READ: How to access ArrayBuffer elements
As with other Scala sequence classes, you access ArrayBuffer
elements by their index, inside parentheses:
val names = ArrayBuffer("bert", "ernie", "oscar") names(0) // "bert" names(1) // "ernie" names(2) // "oscar"
You can also read/access ArrayBuffer
elements in for
loops and for
expressions, as shown here:
val oneToFive = ArrayBuffer(1, 2, 3, 4, 5) for (i <- oneToFive) yield i // ArrayBuffer(1, 2, 3, 4, 5) for (i <- oneToFive) yield i * 2 // ArrayBuffer(2, 4, 6, 8, 10) for (i <- oneToFive) yield i % 2 // ArrayBuffer(1, 0, 1, 0, 1)
UPDATE: Append, prepend, insert, and clear
To update existing elements in an ArrayBuffer
:
val a = (1 to 4).toBuffer // ArrayBuffer(1, 2, 3, 4)
a(2) = 50 // ArrayBuffer(1, 2, 50, 4)
a.update(0, 10) // ArrayBuffer(10, 2, 50, 4)
a.update(3, 40) // ArrayBuffer(10, 2, 50, 40)
Updating also means adding new elements to an ArrayBuffer
, and to do that, use the +=
and ++=
methods:
Method | Description |
---|---|
+= |
add a single element to an ArrayBuffer |
++= |
add a sequence to an ArrayBuffer |
You can also use these methods to append, insert, and prepend elements:
append
,appendAll
insert
,insertAll
prepend
,prependAll
Examples
This is how to use +=
and ++=
:
val nums = ArrayBuffer(1, 2, 3) // ArrayBuffer(1, 2, 3)
nums += 4 // ArrayBuffer(1, 2, 3, 4)
nums ++= List(5, 6) // ArrayBuffer(1, 2, 3, 4, 5, 6)
Other ways to add elements to an ArrayBuffer
:
val a = ArrayBuffer(1, 2, 3) // ArrayBuffer(1, 2, 3)
a.append(4) // ArrayBuffer(1, 2, 3, 4)
a.appendAll(Seq(5, 6)) // ArrayBuffer(1, 2, 3, 4, 5, 6)
a.clear // ArrayBuffer()
val a = ArrayBuffer(9, 10) // ArrayBuffer(9, 10)
a.insert(0, 8) // ArrayBuffer(8, 9, 10)
a.insertAll(0, Vector(6, 7)) // ArrayBuffer(6, 7, 8, 9, 10)
a.prepend(5) // ArrayBuffer(5, 6, 7, 8, 9, 10)
a.prependAll(Seq(1,2,3,4)) // ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
Note that when using insert
, the first parameter is the position at which new elements should be inserted:
val a = ArrayBuffer('a', 'b', 'd') // ArrayBuffer(a, b, d)
a.insert(2, 'c') // ArrayBuffer(a, b, c, d)
UPDATE: ArrayBuffer “in place” methods
Because ArrayBuffer
is mutable, it has “in place” versions of the functional methods you find on immutable collections. As their names imply, they let you mutate an ArrayBuffer
in place. These examples show how these “in place” methods work:
// an example ArrayBuffer:
val a = ArrayBuffer.tabulate(10)(i => i + 1) // a: ArrayBuffer(1 .. 10)
a.dropInPlace(1) // ArrayBuffer(2, 3, 4, 5, 6, 7, 8, 9, 10)
a.dropRightInPlace(1) // ArrayBuffer(2, 3, 4, 5, 6, 7, 8, 9)
a.dropWhileInPlace(_ < 4) // ArrayBuffer(4, 5, 6, 7, 8, 9)
a.filterInPlace(_ > 4) // ArrayBuffer(5, 6, 7, 8, 9)
a.mapInPlace(_ * 10) // ArrayBuffer(50, 60, 70, 80, 90)
a.takeInPlace(4) // ArrayBuffer(50, 60, 70, 80)
a.takeRightInPlace(3) // ArrayBuffer(60, 70, 80)
a.takeWhileInPlace(_ < 80) // ArrayBuffer(60, 70)
// sortInPlace
val b = ArrayBuffer(20, 10, 15, 30, 25)
b.sortInPlace // ArrayBuffer(10, 15, 20, 25, 30)
b.sortInPlaceWith(_ < _) // ArrayBuffer(10, 15, 20, 25, 30)
b.sortInPlaceWith(_ > _) // ArrayBuffer(30, 25, 20, 15, 10)
Note that the sorting examples require that the data type inside the ArrayBuffer
is “sortable,” and I explain that more in How to sort Scala collections classes.
DELETE: Removing elements from an ArrayBuffer
An ArrayBuffer
is a mutable sequence, so:
Method | Description |
---|---|
-= |
Remove a single element or tuple of elements |
--= |
remove multiple elements that are declared in another collection |
clear |
removes all the elements from an ArrayBuffer |
reduceToSize |
removes all elements after the index you specify |
remove |
Use remove to delete one element by its position in the ArrayBuffer, or a series of elements beginning at a starting position |
trimStart |
remove elements from the beginning |
trimEnd |
remove elements from the end |
Examples
-=
and --=
:
val a = ArrayBuffer.range('a', 'h') // ArrayBuffer(a, b, c, d, e, f, g) a -= 'a' //
ArrayBuffer(b, c, d, e, f, g)a --= Seq('b', 'c') //
ArrayBuffer(d, e, f, g)a --= Set('d') //
ArrayBuffer(e, f, g)
remove
:
val a = ArrayBuffer.range('a', 'h') // ArrayBuffer(a, b, c, d, e, f, g)
a.remove(0) // ArrayBuffer(b, c, d, e, f, g)
a.remove(2, 3) // ArrayBuffer(b, c, g)
trimStart
and trimEnd
:
val a = ArrayBuffer.range('a', 'h') // ArrayBuffer(a, b, c, d, e, f, g)
a.trimStart(2) // ArrayBuffer(c, d, e, f, g)
a.trimEnd(2) // ArrayBuffer(c, d, e)
clear
:
val a = ArrayBuffer.range('a', 'h') // ArrayBuffer(a, b, c, d, e, f, g)
a.clear // ArrayBuffer[Char] = ArrayBuffer()
reduceToSize
:
val a = ArrayBuffer.range('a', 'h') // ArrayBuffer(a, b, c, d, e, f, g)
a.reduceToSize(4) // ArrayBuffer(a, b, c, d)
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
MORE: Using functional methods with ArrayBuffer
Even though ArrayBuffer
is a mutable sequence, you can also use all of the usual functional methods to create new values from an ArrayBuffer
:
val a = ArrayBuffer.range(0,5) // ArrayBuffer(0, 1, 2, 3, 4)
val b = a.head // b = 0
val b = a.tail // b = ArrayBuffer(1, 2, 3, 4)
val b = a.drop(2) // b = ArrayBuffer(2, 3, 4)
val b = a.dropWhile(_ < 3) // b = ArrayBuffer(3, 4)
val b = a.take(2) // b = ArrayBuffer(0, 1)
val b = a.takeWhile(_ < 3) // b = ArrayBuffer(0, 1, 2)
val b = a.map(_ * 2) // b = ArrayBuffer(0, 2, 4, 6, 8)
val b = a.filter(_ > 2) // b = ArrayBuffer(3, 4)
val a = ArrayBuffer.range('a', 'e') // ArrayBuffer(a, b, c, d)
val b = a.splitAt(2) // b = (ArrayBuffer(a, b),ArrayBuffer(c, d))
You can also convert ArrayBuffer
into other Scala sequences:
val a = ArrayBuffer.range(0,4) // ArrayBuffer(0, 1, 2, 3)
val b = a.toList // b = List(0, 1, 2, 3)
val b = a.toVector // b = Vector(0, 1, 2, 3)
val b = a.toSet // b = Set(0, 1, 2, 3)
For many more examples of using functional methods on Scala sequences, see my Examples of Scala Vector methods tutorial.
Scala ArrayBuffer summary
I hope these ArrayBuffer
examples are helpful. If I made a mistake, or you know another way to do something with an ArrayBuffer
I haven’t shown, leave a note in the Comments section.