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

CollectionOrderDuplicatesBest Use
ListKeptAllowedQuery results, records to insert or update
SetNot guaranteedNot allowedCollecting unique Ids or names
MapNot guaranteedKeys must be uniqueFast 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.