In This Article
- A Quick Note on Performance (Big-O)
- Mutable vs. Immutable Collections
- Arrays: Ordered Lists
- Accessing Array Elements
- Modifying Arrays
- Iterating Over Arrays
- Array Performance
- Dictionaries: Key-Value Pairs
- Accessing and Modifying Dictionaries
- Iterating Over Dictionaries
- Dictionary Performance
- Sets: Unique Values
- Choosing the Right Collection
- Exercises
- Key Points
So far, you've stored single values in constants and variables. But real apps deal with collections of data: a list of chat messages, a dictionary of user settings, a set of unique tags. Swift gives you three collection types, each optimized for different use cases.
A Quick Note on Performance (Big-O)
When choosing a collection type, you should consider how fast different operations are. Computer scientists describe this with Big-O notation:
- O(1) — constant time. The operation takes the same amount of time regardless of how many elements are in the collection. Instant.
- O(n) — linear time. The operation gets proportionally slower as the collection grows. Scanning through every element is O(n).
You don't need to memorize formulas. Just know: O(1) is fast, O(n) scales with size. We'll note the performance of key operations for each collection type.
Mutable vs. Immutable Collections
The same let/var rule applies to collections. Use let for collections that won't change, var for ones that will:
Arrays: Ordered Lists
An array is an ordered collection of values of the same type. Elements are accessed by their index (position), starting from 0.
Accessing Array Elements
Unlike first and last (which return optionals), subscript access like players[5] crashes if the index is out of bounds. Always check count first or use safe patterns like first/last when the array might be empty.
Modifying Arrays
Iterating Over Arrays
Array Performance
| Operation | Description | Time |
|---|---|---|
| Access by index | array[i] | O(1) |
| Append to end | array.append(x) | O(1)* |
| Insert at beginning | array.insert(x, at: 0) | O(n) |
| Remove last | array.removeLast() | O(1) |
| Remove at index | array.remove(at: i) | O(n) |
| Search | array.contains(x) | O(n) |
*Amortized O(1) — occasionally O(n) when the array needs to resize.
Dictionaries: Key-Value Pairs
A dictionary is an unordered collection of key-value pairs. Keys must be unique and Hashable. Values are accessed by key, not by index.
Accessing and Modifying Dictionaries
Unlike arrays (which crash on bad indices), dictionary subscripts return nil when the key doesn't exist. This is safer but means you need to unwrap the result with if let, guard let, or ??.
Iterating Over Dictionaries
Dictionary Performance
| Operation | Description | Time |
|---|---|---|
| Access by key | dict["key"] | O(1) |
| Insert/update | dict["key"] = value | O(1) |
| Remove | dict["key"] = nil | O(1) |
| Search | dict["key"] != nil | O(1) |
Everything is O(1). Dictionaries trade ordering for speed. If you need fast lookups by a key, dictionaries are the right choice.
Sets: Unique Values
A set is an unordered collection of unique values. Duplicates are automatically removed. Elements must be Hashable.
Sets are ideal when you need to answer "is X in this collection?" as fast as possible, or when you need to guarantee uniqueness.
Choosing the Right Collection
| Need | Use | Why |
|---|---|---|
| Ordered list, access by position | Array | O(1) index access, maintains order |
| Look up values by a key | Dictionary | O(1) key lookup, no ordering needed |
| Check membership, guarantee uniqueness | Set | O(1) contains check, auto-deduplication |
Exercises
Try These in Your Playground
- Create an array of your 5 favorite foods. Print the first and last items. Append a 6th item. Remove the 3rd item.
- Write a function
removingOnce(_ item: Int, from array: [Int]) -> [Int]that removes only the first occurrence of an item. - Write a function
reversed(_ array: [Int]) -> [Int]that reverses an array without using the built-inreversed()method. - Create a dictionary mapping country codes to country names (e.g.,
["US": "United States", "JP": "Japan"]). Add a new country. Look up a code that doesn't exist and handle thenilresult. - Write a function
occurrencesOfCharacters(in text: String) -> [Character: Int]that counts how often each character appears in a string. - Create a set from the array
[1, 2, 3, 2, 1, 4]. Print the count. Check if it contains 5. - Challenge: Write a function
isInvertible(_ dict: [String: Int]) -> Boolthat returns true if all values in the dictionary are unique. (Hint: use a Set.)
Key Points
What You Learned
- Arrays are ordered, indexed collections — use when order matters
- Array subscripts crash on out-of-bounds;
first/lastreturn optionals safely - Use
append,insert,remove, and subscript assignment to modify arrays - Iterate with
for-in; useenumerated()to get indices alongside values - Dictionaries are unordered key-value pairs — use for fast lookups by key
- Dictionary subscripts return optionals (
nilif key not found) - Set a dictionary value to
nilto remove the pair - Sets are unordered collections of unique values — use for membership checks and deduplication
- All basic Swift types are
Hashable, so they work as dictionary keys and set elements - Use
letfor immutable collections,varfor mutable ones - Know the performance trade-offs: arrays excel at indexed access, dictionaries and sets excel at lookups
This chapter completes Section II: Collection Types of the Swift fundamentals. In the next chapter, we'll begin Section III: Building Your Own Types — starting with closures, then moving into structs, classes, and protocols.
Watch the video lessons
Our Swift Fundamentals course has 27 dedicated video lessons on collections — arrays, dictionaries, and real-world data patterns.
Watch Swift Videos