Part 17: Collections
Until now every sequence had a length fixed while compiling. Real data rarely does: lines read from a file, orders placed today, words in a text. This part introduces the containers of the Collections package, which hold as many values as arrive and manage their own memory through an allocator. By the end you will know eleven of them, what each is quick and slow at, and which to reach for.
What you will learn
Vector<T>, the growable sequence, and the difference between its length and its capacity.Array<T>, a sequence whose length is chosen at run time and then fixed.Deque<T>, quick at both ends — the natural queue.HashMap<K, V>andHashSet<T>: lookup by key and membership tests in about constant time, with no order.TreeMap<K, V>andTreeSet<T>: the same, kept sorted, with ordered questions such asFloor,CeilingandRange.PriorityQueue<T>, which always hands out its largest element next, by the element's own<.BitSet, a set of small integers at one bit each, with union, intersection and difference a word at a time.SmallVector<T>, a vector that keeps its first few elements inside itself and allocates only past them.LruCache<K, V>, a map of bounded size that forgets the entry used least recently.- The pattern every collection shares: made from an allocator, fallible where it needs memory, optional where a value may be missing, and freed by its destructor.
Which collection?
flowchart LR
q{"How do you find<br/>a value again?"} -- "by position" --> pos{"How does the<br/>length change?"}
pos -- "never — known<br/>while compiling" --> inline["Inline array<br/>`T[n]`"]
pos -- "never — known<br/>only at run time" --> arr["`Array`"]
pos -- "values come and go<br/>at the end" --> vec["`Vector`"]
pos -- "values come and go<br/>at both ends" --> dq["`Deque`"]
q -- "by key" --> korder{"Do the keys need<br/>to stay in order?"}
korder -- "no" --> hm["`HashMap`"]
korder -- "yes" --> tm["`TreeMap`"]
q -- "only: is it here?" --> sorder{"Do the members need<br/>to stay in order?"}
sorder -- "no" --> hs["`HashSet`"]
sorder -- "yes" --> ts["`TreeSet`"]When in doubt, start with a Vector for a list and a HashMap for lookups. Switch to a Deque when values join at the front, and to a tree when the order of the keys is part of the answer.
The last four lessons are specialists, each the better choice for one particular job:
| When you need… | Reach for | Instead of |
|---|---|---|
| always the most urgent item next | PriorityQueue | sorting a Vector each time |
| a set of small integers, and fast set operations | BitSet | a HashSet of numbers |
| many short lists, without an allocation each | SmallVector | a Vector |
| a lookup table that must not grow without limit | LruCache | a HashMap |
Lessons
| Lesson | What you will learn | |
|---|---|---|
| 17.1 | Vector | a growable array that manages its own memory and capacity |
| 17.2 | Dynamic array | Collections::Array, and how it differs from an inline array |
| 17.3 | Deque | add and remove at both ends, and see where that beats a vector |
| 17.4 | Hash map | look values up by key |
| 17.5 | Hash set | test membership with a hash set |
| 17.6 | Tree map | keep keys in order, and walk them in order |
| 17.7 | Tree set | keep a set of values in order |
| 17.8 | Priority queue | always take the most urgent item next |
| 17.9 | Bit set | a set of small integers kept as bits |
| 17.10 | Small vector | a vector that keeps its first few items without allocating |
| 17.11 | LRU cache | a bounded cache that forgets the least recently used entry |
Before you start
Every collection takes an allocator, so finish Part 15: Memory first. The lessons also lean on generic types from Part 13, a fallible Main and ? from Part 9, optionals from Part 8, moves from Part 11, Comparable and Operator overload from Part 12, and Bitwise from Part 16. Each lesson's package is in the Examples repository's Collections/ folder:
cd Examples/Collections/Vector
rux run
After this part
Part 18: Algorithms sorts, searches and folds the values you can now collect. Parts 18 to 26 tour the standard packages and can be read in any order. Before moving on, try the checkpoint projects Word count, which counts words in a hash map and prints them in order through a tree map, and Inventory, a shop's stock kept as structs in a vector.
For the rules behind the inline sequences these containers are compared with, see Arrays and Slices in the Rux Reference.
16.12 Complex
Do arithmetic on complex numbers with the Math package's Complex and its four operators, read one as a length and an angle with Abs and Arg, build one with FromPolar, and solve a quadratic whose roots are not real.
17.1 Vector
Push values into a Vector<T> and watch its length and capacity grow apart.