2

I am having trouble understanding how maps are populated in Salesforce. For example, what happens in the situation below:

Edited code below:

Map<Id, Account> accountMap = new Map<Id, Account>([SELECT Id, FirstName, LastName FROM Account]);

What is the key and what is the value here? What happems if you have multiple fields in the query? The SOQL statement returns a list of Accounts so how does does the map get populated?

For Governor Limits, there is a 6MB heap limit for general usage of Maps and Lists. However, during Bulk triggers, Lists can take up to 200 records. Is there a limit on how many record a Map can take during bulk?

I realise there are a few questions here but I can't seem to find any information about these questions I have. Any help appreciated!

8

The code

map<ID, String> = [select ID, FirstName, LastName from Account];

is not valid, for several different reasons. The idiom you're looking for is this:

Map<Id, Contact> contactMap = new Map<Id, Contact>([SELECT Id, FirstName, LastName FROM Contact]);

It's essentially a convenience constructor for Map<Id, sObject> types that will populate the map by keying each sObject in the List under its Id value.

This is very useful for accessing fields while correlating multiple sObjects. For example, in a Contact trigger, you might do

Map<Id, Account> accountMap = new Map<Id, Account>([SELECT Id, Name FROM Account WHERE Id IN :myIdSet]); 
// Suppose we previously collected AccountIds from our Contacts in this set

for (Contact c : myContactList) {
    Account a = accountMap.get(c.AccountId);
    // Do things with the Account's field values.
    System.debug(a.Name);
}

The queried fields live on the sObject instances that are the values of the Map.

There is no limit on record count in a Map or a List as such, but the heap limit does apply. You will in most instances not be able to run a query like that without WHERE filters in any context outside of Batch Apex or the Bulk API; the query will likely timeout before it hits the heap limit, but it'll hit some governor limit.

  • Neck and neck, we were. +1 from me. – Derek F Jun 19 '18 at 21:37
  • So many useful answers, its hard to pick 1 to accept – M guy Jun 19 '18 at 21:38
  • I am currently perusing the Platform Developer 1 certification. Any advice or tips? The question was really related to my training. – M guy Jun 19 '18 at 21:40
  • @Mguy, that's a topic better suited for another forum than an SFSE comment thread. – David Reed Jun 19 '18 at 21:42
7

It's magic (by that, I mean that Salesforce doesn't tell us exactly how they do it).

The syntax in your original question is incorrect, and will not compile when you try to save/execute/deploy (the current edit at time of writing uses correct syntax). Using the correct syntax will give you some clues.

Map<Id, Account> myMap = new Map<Id, Account>([SELECT Id, Name FROM Account]);

SOQL returns to you either a List<SObject>, or a List<AggregateResult> (if you use the GROUP BY keyword).

The Map class (relevant documentation) contains a constructor that can take a List<Sobject>, and give you a Map<Id, SObject> in return.

The Map key when you use this constructor is always an Id. Specifically, the Id of the SObject at the root of the query (i.e. the object you name in the WHERE clause). There is a way to trick Salesforce into using a different Id, but that's out of scope for this question.

The value is always an SObject, and if your Map specifies a specific SObject like Account, Salesforce will automatically take care of type casting. How exactly Salesforce accomplishes that is the "magic" here.

Because it's an SObject, it won't matter how many fields you query. .get() a record from the map, and you can use it exactly like any other SObject instance because it is an SObject instance

0
  1. You can't query into a Map unless that Map has Id or String as the key and an sObject as the value. Example from the docs:

    Map<ID, Account> m = new Map<ID, Account>([SELECT Id, Name FROM Account LIMIT 10]);

  2. The Trigger.oldMap and Trigger.newMap maps will contain the same records as the Trigger.old and Trigger.new Lists, also maxing at the the 200 record batch size. If you are querying for and creating other maps of records in your trigger, they will be governed by the Heap limit, not a record limit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.