Friday, November 2, 2012

Converting a List (of sObjects) to a Map

This article assumes you already know Salesforce's powerful way to collect objects, List, Map and Set.  If you are not familiar with them, you should go to the documentation for more information first.

What I found somewhat undocumented (it actually is documented but you don't find its usage this way in a lot of places) is a way you can initialize a Map collection.  You probably already know Map is used to provide a mapping between a primitive type (such as Integer, String, etc. used as the key) and practically any other type (used as the value).  A simple example is:

Map<Integer, String> myMap1 = new Map<Integer, String>{ 1 => 'a', 2 => 'b'};

The above declares a map variable, called myMap1 which contains 2 elements.  The first element contains a mapping from the integer 1 to the string a, and the second element contains a mapping from the integer 2 to the string b.

The "value" does not have to a primitive type - it can be an sObject, for example.

Map<Id, Account> myMap2 = new Map<Id, Account>();

The above is a variable myMap2 that stores a mapping between Id and the account sObject.

If you have run a SOQL statement and has retrieved a list of contacts, such as:

List<Contact> myContactList1 = [SELECT Id FROM Contact];

you can then "convert" this list to a map, by doing this:

Map<Id, Contact> myMap3 = new Map<Id, Contact>(myContactList1);

The new operator will convert this list (myContactList1) to create the map variable myMap3.  The key of myMap3 is obviously the Id field because that is what is selected.  In fact, Id is always used as the key in this context.  It is also always implicit.  So even if your SOQL had been:

List<Contact> myContactList2 = [SELECT Title FROM Contact];

the key will still be the Id field of Contact.  I think the Id will be based on what sObject you are selecting from.  In this case, it is the Contact, and therefore the Id will be the id of contacts.

The value part, however, is dependent on what you "select".  The list myContactList1 only selects the Id field, so the value only contains the Id field as well.  The list myContactList2 however, selects the Title field, so you can actually access the Title field via this myContactList2 collection.

Let's say you have a contact named Tim Barr.  If you run the following statements, you will see that in the debug log, the value for this contact contains the Id as well as the Title.

Contact c = [SELECT Id from Contact where FirstName = 'Tim' and LastName='Barr'];
List<Contact> myContactList2 = [SELECT Title FROM Contact];
Map<Id, Contact> myMap3 = new Map<Id, Contact>(myContactList2);
system.debug(myMap3.get(c.Id));


It seems to be the Id field is again implicit in the value too.  The SELECT clause determines what other fields are available in the value.

1 comment:

Please leave a comment.