Undercover Maps

Eyes hiding behind a map.The Map class is probably the most useful collection on the Salesforce platform.

When you combine a Map with a SOQL query you have a really cool tool for automatically populutating a Map of SObjects keyed on Id using a special Map constructor:

Map<Id, Account> accountMap = new Map<Id, Account>([Select Id, Name From Account]);

This is well documented (and really useful for bulk loading foreign objects in triggers) but it turns out you can use this map constructor to populate a Map from any list of SObjects.

In the following example we have a query that loads Accounts as well as Opportunities. You can use the Map constructor to load the subquery results into a Map as follows:

// Query Accounts and Opportunities into a Map
Map<Id, Account> accountMap = new Map<Id, Account>([Select Id, Name, (Select Id, Name From Opportunities) From Account]);

// Iterate over the Map keys
for (Id key : accountMap.keySet())
    Account acc = accountMap.get(key);

    System.debug('Account: ' + key + ' => ' + acc.Name);

    // Load the Opportunities into a Map
    Map<Id, Opportunity> oppMap = new Map<Id, Opportunity>(acc.Opportunities);

    // Iterate over the Map Keys
    for (Id key2 : oppMap.keySet())
        Opportunity opp = oppMap.get(key2);

        System.debug('Opportunity: ' + key2 + ' => ' + opp.Name);

You can do the same with Dynamic SOQL with one subtle difference, you need to check for Nulls:

// Query to execute
String query = 'Select Id, Name, (Select Id, Name From Opportunities) From Account';

// Query Accounts and Opportunities into a Map
Map<Id, SObject> sObjectMap = new Map<Id, SObject>(Database.query(query));

// Iterate over the Map keys
for (Id key : sObjectMap.keySet())
    SObject so = sObjectMap.get(key);

    System.debug('Account SObject: ' + key + ' => ' + so.get('Name'));

    // Load the Opportunities into a Map
    List<SObject> sos = so.getSObjects('Opportunities');

    // Check the Map for Null in case the Account has no Opportunities
    if (sos != null)
        Map<Id, SObject> soMap2 = new Map<Id, SObject>();

		// Iterate over the Map keys
        for (Id key2 : soMap2.keySet())
            SObject so2 = soMap2.get(key2);

            System.debug('Opportunity SObject: ' + key2 + ' => ' + so2.get('Name'));

The Map constructor also allows you to use a Dynamic SOQL query to load into Map of concrete SOBjects by casting it to a List:

String query = 'Select Id, Name From Account';

Map<Id, Account> accountMap = new Map<Id, Account>((List<Account>)Database.query(query));

A Final Word of Warning:

Always exercise caution when using undocumented features within Salesforce. They may break without warning.


Author, brainstormer, coder, dad, explorer, four chord trickster, gig goer, home worker, inquisitor, joker, knowledge seeker, likes: marmite, note scribbler, opinionator, poet, quite likes converse, roller skater, six music listener, tea drinker, urban dweller, vinyl spinner, word wrangler, x-factor hater, Yorkshireman (honorary), zombie slayer (lie).

Tagged with: ,
Posted in apex, code, force.com, salesforce
About Me
Product Services Developer at:
All views expressed here are my own. More about me and contact details here.
Please sponsor me …
My wife and I are running the Great North Run to support The Nick Alexander Memorial Trust

If you've found my blog useful, please consider sponsoring us. Sponsor me on BT MyDonate

Enter your email address to follow this blog and receive notifications of new posts by email.

Copyright (there isn’t any, feel free to reuse!)

To the extent possible under law, Tony Scott has waived all copyright and related or neighboring rights to MeltedWires.com Examples and Code Samples. This work is published from: United Kingdom.

%d bloggers like this: