While working on Developer forum i found lots of question for List ,Set and Map, like below
1) When we should use Map over the list
2) When do we use set, Map,List
3) Bulkify code with Map
4) Using Maps and Sets in Bulk Triggers
5) Use of Map in Apex class.
6) Map over list to avoid query inside for loop
Solution :-
List, Set, Map are called collections in Apex:
List : A list is an ordered collection
1) so use list when you want to identify list element based on Index Number.
2) list can contain Duplicates
EX: List<Account> accList = new List<Account>();
Set : A set is an unordered collection
1) Do not contain any duplicate elements. So, use set if you want to make sure that your collection should not contain Duplicates.
EX: Set<Account> accSet = new Set<Account>()
Set<String> setString = new Set<String>(); // Add two strings to it setString .add('item1'); setString .add('item2');
Map : A map is a collection of key-value pairs
Each unique key maps to a single value. Keys can be any primitive data type, while values can be a primitive, sObject, collection type or an Apex object.
EX: Map<Id, Account> accMap = new Map<Id, Account>();
Map<Integer, String> mapOfString = new Map<Integer, String>(); mapOfString.put(1, 'Amit'); mapOfString.put(2, 'Rahul'); System.assert(mapOfString.containsKey(1));
String value = mapOfString.get(2);
System.assertEquals('Rahul', value); Set<Integer> s = mapOfString.keySet();
Map<
String
,
String
> myMap =
new
Map<
String
,
String
>{
'a'
=>
'b'
,
'c'
=>
'd'
};
Example 1:- Using trigger populate the Account Field on the Contact record (only insert scenario)
If we use List and not Map
Apex Class
trigger ContactTriggerWithList on Contact (before insert)
{
Set<Id> SetAccountId = new Set<Id>(); // Use set to collect unique account ID
for(Contact con: Trigger.new)
{
if(con.AccountId != null)
{
SetAccountId.add(con.AccountId); // add Account in Set
}
}
if( SetAccountId.size() >0 )
{
List<Account> listAccount = [ Select Id, Name, Type from Account where Id IN :SetAccountId ]; // Query Related Account
for(Contact con: Trigger.new)
{
if(con.AccountId != null)
{
for(Account acc: listAccount)
{
if(con.AccountId == acc.Id)
{
con.Type__c = acc.Type;
}
}
}
}
}
}
NOTE:- In this we are using List of Accounts, Where we have to loop through the matching Account every time to populate the Type__c in the second for loop. In this case need to use nested loop.
To Above the Nested Loop We can use the Map .
Same Trigger using the Map:
trigger ContactTriggerWithMap on Contact (before insert)
{
Set<Id> SetAccountId = new Set<Id>();
for(Contact cont: Trigger.new)
{
if(cont.AccountId != null)
{
SetAccountId.add(cont.AccountId);
}
}
if(SetAccountId.size() > 0 )
{
Map<Id, Account> mapAccount = new Map<Id, Account>([Select Id, Name, Type from Account where Id IN :SetAccountId ]);
for(Contact cont: Trigger.new)
{
if(cont.AccountId != null && mapAccount.containsKey(cont.AccountId) )
{
cont.Type__c = mapAccount.get(cont.AccountId).Type;
}
}
}
}
NOTE:- Here we are using map of Account so we can directly use the Map to get the Account record. No need of 2nd for loop here
Related Link :-
1) https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_collections.htm
2) https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_bulk_idioms.htm
3) https://developer.salesforce.com/page/Apex_Code_Best_Practices
Thanks,
Amit Chaudhary