Salesforce Apex Collections
A shopping bag holds many items. A guest list holds unique names. A phone book links names to numbers. Apex gives developers three collection types that match these everyday objects: Lists, Sets, and Maps. Collections matter in Salesforce because the platform processes records in groups, and developers need clean containers to carry those groups.
List: An Ordered Bag of Items
A List keeps items in order and allows duplicates. Each item has a position number, called an index, that starts at zero.
List<String> fruits = new List<String>();
fruits.add('Apple');
fruits.add('Mango');
fruits.add('Apple');
String first = fruits[0]; // Apple
Integer total = fruits.size(); // 3
Index: 0 1 2
+-------+---------+-------+
| Apple | Mango | Apple |
+-------+---------+-------+
Lists work best when order matters or when a SOQL query returns records. A query such as SELECT Id, Name FROM Account returns a List of Account records.
Set: A Guest List With No Duplicates
A Set stores unique values with no guaranteed order. Adding the same value twice leaves a single copy.
Set<String> cities = new Set<String>();
cities.add('Delhi');
cities.add('Pune');
cities.add('Delhi');
Integer count = cities.size(); // 2
Boolean found = cities.contains('Pune'); // true
Sets answer the question "Does this value exist?" very quickly. Developers often collect record Ids in a Set and pass the Set into a SOQL query with the IN keyword.
Map: A Phone Book of Keys and Values
A Map links a key to a value. The key finds the value instantly, with no searching through every item.
Map<String, Integer> stock = new Map<String, Integer>();
stock.put('Pen', 50);
stock.put('Book', 20);
Integer pens = stock.get('Pen'); // 50
Boolean has = stock.containsKey('Bag'); // false
Key Value +------+ +----+ | Pen | > | 50 | | Book | > | 20 | +------+ +----+
Choosing the Right Collection
| Collection | Order | Duplicates | Best Use |
|---|---|---|---|
| List | Kept | Allowed | Query results, records to insert or update |
| Set | Not guaranteed | Not allowed | Collecting unique Ids or names |
| Map | Not guaranteed | Keys must be unique | Fast lookup by Id or name |
The Id-to-Record Map Shortcut
Salesforce developers rely on one special pattern. Passing a SOQL query into a Map constructor builds a Map where each key is the record Id and each value is the full record.
Map<Id, Account> accountMap = new Map<Id, Account>(
[SELECT Id, Name, Industry FROM Account LIMIT 100]
);
Account acc = accountMap.get(someAccountId);
The pattern replaces a nested loop with a direct lookup. Triggers use it constantly to match Contacts with their parent Accounts.
Looping Through Collections
A for loop visits every item.
for (String fruit : fruits) {
System.debug(fruit);
}
A Map loop usually iterates over the keySet or the values method.
for (String item : stock.keySet()) {
System.debug(item + ' = ' + stock.get(item));
}
Example Scenario: Find Accounts Without Contacts
A developer needs a list of accounts that have no contacts.
Query all Accounts ----------> List of Accounts
Query Contacts by AccountId --> Set of AccountIds that HAVE contacts
Loop Accounts:
Is Account Id in the Set?
Yes --> skip
No --> add to result List
Set<Id> withContacts = new Set<Id>();
for (Contact c : [SELECT AccountId FROM Contact WHERE AccountId != null]) {
withContacts.add(c.AccountId);
}
List<Account> lonely = new List<Account>();
for (Account a : [SELECT Id, Name FROM Account]) {
if (!withContacts.contains(a.Id)) {
lonely.add(a);
}
}
The Set makes each check fast, and the code runs only two queries no matter how many records exist.
Useful Methods at a Glance
Each collection type ships with helper methods that save developers from writing loops by hand. A List offers add, addAll, remove, clear, isEmpty, contains, and sort. A Set offers add, addAll, remove, contains, and retainAll, which keeps only values that two Sets share. A Map offers put, get, remove, containsKey, keySet, and values. Learning these names lets a developer express an idea in one line instead of ten.
Sorting deserves special attention. The sort method on a List of strings or numbers arranges items in ascending order. A List of records sorts through a custom class that implements the Comparable interface, which tells Apex how to compare two records.
Collections and Governor Limits
Salesforce limits how much memory a transaction can use. A List that holds 50,000 full records consumes far more heap space than a Set of 50,000 Ids. Select only the fields the code needs, and prefer Sets of Ids when a full record is unnecessary. Lean collections keep the transaction well below the heap ceiling.
Best Practices
- Declare collections with specific types, such as List<Account>, to catch mistakes at compile time.
- Use a Set to remove duplicates before a query.
- Use a Map for repeated lookups instead of nested loops.
- Keep SOQL queries outside loops and fill collections first.
- Check size before reading index zero, because an empty List throws an error.
