The Apex language provides developers with three classes (Set, List and Map) that make it easier to handle collections of objects. In a sense these collections work somewhat like arrays, except their size can change dynamically, and they have more advanced behaviors and easier access methods than arrays. If you are familiar with the Java Collections API then these should feel very warm and cozy. Each collection has characteristics that make it applicable in certain situations and we'll cover these in detail. We'll talk about each of the collections, their features, how they are typically used and show some sample code that you can execute in your org.
Note: Salesforce.com recently made an important change to collections. There is no longer a limit on the number of items a collection can hold. However, there is a general limit on heap size.
I tried to fit virtually everything that I could about collections onto a single blog post hoping it will make good Evernote fodder. If I left something out, please drop a comment below.
Set
A set is a collection of unique, unordered elements. It can contain primitive data types (String, Integer, Date, etc) or sObjects. If you need ordered elements use a List instead. You typically see Sets used to store collections of IDs that you want to use in a SOQL query.
The basic syntax for creating a new Set is:
Examples:
As mentioned before one of the main characteristics of a Set is the uniqueness of elements. You can safely try to add the same element (e.g., 100, 'c', 125.25) to a Set more than once and it will just disregard the duplicate (without throwing an Exception). However, there is a slight twist when dealing with sObjects. Uniqueness of sObjects is determined by comparing fields in the objects. The following code will result in only one element in the Set.
Different field values cause the objects to become unique.
Set Methods
There are a number Set methods so check out the docs for a complete list, but here are some of the more common ones you might use. You can paste the following snippet of code into your browser's System Log and run it anonymously.
You should see the following (abbreviated) output:
DEBUG|=== number of elements: 4
DEBUG|=== number of elements: 3
DEBUG|=== set contains element Jon: true
DEBUG|=== element : Jon
DEBUG|=== element : Quinton
DEBUG|=== element : Sandeep
DEBUG|=== contents of s1: {Jon, Quinton, Sandeep}
DEBUG|=== is the s1 set empty? true
Commonly you'll see developers construct a Set of IDs from a query, trigger context, etc. and then use it as part of the WHERE clause in their SOQL query:
List
Lists are the mostly widely used collection so learn to love them (I do!!). A List is a collection of primitives, user-defined objects, sObjects, Apex objects or other collections (can be multidimensional up to 5 levels). Use a List (as opposed to a Set) when the sequence of elements is important. You can also have duplicate elements in a List. List are zero-based so the first element in the List is always 0.
The basic syntax for creating a new List is:
Examples:
Lists and Arrays are pretty much interchangeable and you can mix and match them:
You should see the following (abbreviated) output:
DEBUG|=== Jon
DEBUG|=== Jon
DEBUG|=== Jon
DEBUG|=== Jon
List Methods
There are a number List methods so check out the docs for a complete list, but here are some of the more common ones you might use. You can paste the following snippet of code into your browser's System Log and run it anonymously.
You should see the following (abbreviated) output:
DEBUG|=== number of elements: 5
DEBUG|=== first element: Jon
DEBUG|=== number of elements: 4
DEBUG|=== contents of s1: (Quinton, Reid, Sandeep, Sandeep)
DEBUG|=== contents of s1: (Quinton, Reid, Sandeep, Pat)
DEBUG|=== sorted contents of s1: (Pat, Quinton, Reid, Sandeep)
DEBUG|=== is the list empty? true
You can use a List of Strings in the same sort of way you would a Set as part of a SOQL query:
Since SOQL queries return Lists of records, you can use them directly for iteration:
You can also use the List in a traditional for loop:
Map
A Map is a collection of key-value pairs. Keys can be any primitive data type while values can include primitives, Apex objects, sObjects and other collections. Use a map when you want to quickly find something by a key. Each key must be unique but you can have duplicate values in your Map.
The basic syntax for creating a new Map is:
Examples:
Map Methods
There are a number Map methods so check out the docs for a complete list, but here are some of the more common ones you might use. You can paste the following snippet of code into your browser's System Log and run it anonymously.
You should see the following (abbreviated) output:
DEBUG|=== all keys in the map: {1, 5, 6}
DEBUG|=== all values in the map (as a List): (Reid, Jon, Quinton)
DEBUG|=== does key 6 exist?: true
DEBUG|=== value for key 6: Quinton
DEBUG|=== size after adding Dave: 4
DEBUG|=== size after removing Jon: 3
DEBUG|=== cloned m1: {1=Reid, 3=Dave, 6=Quinton}
DEBUG|=== is m empty? true
Maps are used very frequently to store records that you want to process or as containers for "lookup" data. It's very common to query for records and store them in a Map so that you can "do something" with them. The query below creates a Map for you where the key is the ID of the record. This makes it easy to find the record in the Map based upon the ID. You can paste the following snippet of code into your browser's System Log and run it anonymously.
You'll use Maps quite a bit when writing triggers. For before update and after update triggers there are two trigger context variables named oldMap and newMap. The oldMap contains a list of sObject before they were modified. The newMap contains a list of sObject with the updated values. You typically use these Maps to make some sort of comparison inside the trigger:
Maps are also used extensively to stay within governors and limits. The following is code from Writing Bulk Triggers in Salesforce.com:
Modifying Collection Elements
Modifying a collection's elements while iterating through that collection is not supported and will throw an error. To add or remove elements for a collection, while iterating over the collection, create a new temporary list with these elements. Then simply add or remove them after you are finished iterating the collection.
Custom Iterators
Apex has the ability to create custom Iterators but that is a little beyond the scope of this post.