Maps in Salesforce
Maps are key-value pairs in any coding language
For me too using a Map was like pain and could never understand its real use. I used to code using list and set without using of a map where it was a must and which intern led to poor coding standards. But after lot of practice and understanding, i have figured out the simplest way to use a map in Salesforce. I would like to share it with you guys.
Syntax of a Map
Map<Key,Value> radicalMap = new Map<Key,Value>();
Key - Unique
Value - Not Unique
Key - Unique
Value - Not Unique
Example for a better understanding:
There is a box which contains sports equipment and its a mixture of 3 different sports. Sports like Hiking, Swimming and Cricket.Now the box contains a Cricket Bat, Hiking Gloves and Mittens, Duffle Bags, Pool Shoes, Ball, Cricket Pads, Bathrobes and Fleeces/Jumpers.
Now Radical Sports team would like to categorize them based on their particular sport.
Key Value
Cricket Cricket Bat
Ball
Cricket Pads
Hiking Hiking Gloves and Mittens
Fleeces/Jumpers
Duffle Bags
Swimming Pool Shoes
Bathrobes
If we try to sync the above categorization with our learning of the Map, the syntax would be as below -
Map<String,List<String>> spMap = new Map<String,List<String>>();
String = Key (Cricket,Hiking and Swimming)
List<String> = Values (Bat,Pool Shoes,...)
We have chosen a list of Strings because under each sport there is a bunch of equipments.
Example 1 with real use of Map :
- We have Account which is the parent object and a contact associated with the account as the child Object. We are going to project the related Account,Contacts in a Visualforce page using an Apex Controller.
- A Constructor in Controller to fetch the required data
- Querying the list of Accounts
- Querying the list of Contacts related to the above fetched Accounts
- A Map to store Key(Account) and Values(list of Contacts)
- Displaying Map on a Visualforce Page
Apex Class :
public class AccountMapClass
{
public List<Account> acclist;
public List<Contact> conList;
public Map<String,List<String>> accConMap{get;set;}
Public AccountMapClass()
{
acclist = [select id,name from Account];
//Fetching the contacts related to above account list
conList = [select id,lastName,accountId from contact
where AccountId in : acclist];
//Initiating the Map
accConMap = new Map<String,List<String>>();
//First we search the contacts list over accounts fetched.
//Iteration is done on AccountList
for(account acc : acclist)
{
List<String> conlistInternal = new List<String>();
//Iteration on Contact List
for(contact con : conList)
{
//If we find any account id related to contact.AccountId
//We are creating a list, adding the contact's LastName
if(acc.id == con.accountId)
{
conlistInternal.add(con.lastName);
}
}
//We put Key(AccountName),Values(list of Contacts)
accConMap.put(acc.name,conlistInternal);
}
}
}
VisualForce Page :
<apex:page controller="AccountMapClass">
<apex:form >
<apex:repeat value="{!accConMap}" var="m">
<b>{!m}</b> -
<apex:repeat value="{!accConMap[m]}" var="c">
{!c} ,
</apex:repeat><br/>
</apex:repeat>
</apex:form>
</apex:page>
OUTPUT :
Example 2 :
An custom field added to Account Object - (Number of Contacts)
A trigger should be written for whenever a contact is created and lookup to account field is filled and saved. The Number of Contacts custom field(Number data type) on the Account should automatically updated with the contacts created.
Apex Trigger :
trigger updateNoOfContacts on Contact(after insert)
{
Map<String,List<string>> accConMap = new Map<String,List<string>>();
Set<String> acc = new Set<String>();
for(Contact c : trigger.new)
{
acc.add(c.accountId);
}
for(String acct : acc)
{
List<String> contlist = new List<String>();
for(Contact c : trigger.new)
{
if(acct == c.AccountId)
contlist.add(c.id);
}
accConMap.put(acct,contlist);
}
List<Account> accObj = new List<Account>();
for(account a : [select id,No_of_Contacts__c from account
where id in : accConMap.KeySet()])
{
if(a.No_of_contacts__c>0){
a.No_of_contacts__c += (accConMap.get(a.id)).size();
accObj.add(a);
}
else
{
a.No_of_contacts__c = 1;
accObj.add(a);
}
}
update accObj;
}
The code above is of a roll up summary field functionality (partially) while using a Lookup relationship instead of a Masterdetail relationship. Your assignment would be to write the same trigger on update and delete of contacts which would update the custom field on the accounts with its associated contacts.
Nested Map
Map in a Map is called a nested map.
Syntax :
Map<String,Map<String,List<String>>> mapOfMaps = new
Map<String,Map<String,List<String>>>();
Say for example, If each of Radical Team Member has an Account related to him and each Account has many contacts associated to it, like shown below :
In this case, we would be iterating over Radical Team Member, in this loop create a map as created in the above examples and at the end of the loop add the key as key as Radical team member and its values be a map consisting of Account as the key of the inner map and list of contacts as values to the inner map which sounds good!!!
Code Snippet :
outerMap of<string,Map<string,List<string>>>
for(Radical Team Member)
{
innerMap of <String,List<String>>
for(Account)
{
New List of Contacts
for(contact)
{
create list of contacts over iterated account
}
add key and values to innerMap
}
add key and values to outerMap
outerMap.put(account,innerMap);
}
Thats it folks ! Your valuable feedback and comments are needed to enhance this post further.
<apex:page controller="AccountMapClass">
<apex:form >
<apex:repeat value="{!accConMap}" var="m">
<b>{!m}</b> -
<apex:repeat value="{!accConMap[m]}" var="c">
{!c} ,
</apex:repeat><br/>
</apex:repeat>
</apex:form>
</apex:page>
A trigger should be written for whenever a contact is created and lookup to account field is filled and saved. The Number of Contacts custom field(Number data type) on the Account should automatically updated with the contacts created.
Apex Trigger :
trigger updateNoOfContacts on Contact(after insert)
{
Map<String,List<string>> accConMap = new Map<String,List<string>>();
Set<String> acc = new Set<String>();
for(Contact c : trigger.new)
{
acc.add(c.accountId);
}
for(String acct : acc)
{
List<String> contlist = new List<String>();
for(Contact c : trigger.new)
{
if(acct == c.AccountId)
contlist.add(c.id);
}
accConMap.put(acct,contlist);
}
List<Account> accObj = new List<Account>();
for(account a : [select id,No_of_Contacts__c from account
where id in : accConMap.KeySet()])
{
if(a.No_of_contacts__c>0){
a.No_of_contacts__c += (accConMap.get(a.id)).size();
accObj.add(a);
}
else
{
a.No_of_contacts__c = 1;
accObj.add(a);
}
}
update accObj;
}
The code above is of a roll up summary field functionality (partially) while using a Lookup relationship instead of a Masterdetail relationship. Your assignment would be to write the same trigger on update and delete of contacts which would update the custom field on the accounts with its associated contacts.
Nested Map
Map in a Map is called a nested map.
Syntax :
Map<String,Map<String,List<String>>> mapOfMaps = new
Map<String,Map<String,List<String>>>();
Say for example, If each of Radical Team Member has an Account related to him and each Account has many contacts associated to it, like shown below :
In this case, we would be iterating over Radical Team Member, in this loop create a map as created in the above examples and at the end of the loop add the key as key as Radical team member and its values be a map consisting of Account as the key of the inner map and list of contacts as values to the inner map which sounds good!!!
Code Snippet :
outerMap of<string,Map<string,List<string>>>
for(Radical Team Member)
{
innerMap of <String,List<String>>
for(Account)
{
New List of Contacts
for(contact)
{
create list of contacts over iterated account
}
add key and values to innerMap
}
add key and values to outerMap
outerMap.put(account,innerMap);
}
Thats it folks ! Your valuable feedback and comments are needed to enhance this post further.
Maps in Salesforce
Reviewed by dasfrogpractice
on
04:08
Rating:
Hi Sai,
ReplyDeleteVery valuable information. Thanks for posting.
I have one clarification.
I guess, in No.of contacts example.
else
{
a.No_of_contacts__c = accConMap.get(a.id)).size(); // a.No_of_contacts__c = 1;
accObj.add(a);
}
Thanks,
Kiran.
Hi Kiran, thanks a ton!
DeleteRegarding the size, they both mean the same. I have written the above for better understanding so that people can have two different lines of code in "if/else" statements... :)
hi guyz are you the same people having name as Radical technologies in pune or different?
ReplyDeleteNope.:) . We are a bunch of people sharing free Knowledge.
DeleteI acknowledge the author for his brilliant work for making this exceptionally useful and informative content to guide us.
ReplyDeletesalesforce onilne forms