Blog

Why Maps are an Apex Developer’s Friend.

Terry Luschen  |  July 18, 2012

When we do a query in Salesforce we get back a list. A list is defined in Apex as being an ordered collection of items that are distinguished by their indices. The list is a very helpful data structure and is very easy to work with.

Here is an example where we query out values into a list, loop through them and then do an update.

list myAccounts = new list();
myAccounts = [Select ID, Name, myCustomField__c From Account Where myCustomField__c = false];

for (Account a : myAccounts ){
  a.myCustomField__c = true;
}

update myAccounts;

That all works great and is the simplest way to perform that action. But what happens when you need to compare values from two lists? We could write an outer and an inner loop to do our matches. It might look like this.

integer myCount = 0;
list myCustomA = new list();
myCustomA = [Select ID, myA__c, myAText__c From CustomA__c Where myA__c = false];

list myCustomB = new list();
myCustomB = [Select ID, myB__c, myBText__c From CustomB__c Where myB__c = false];

//Now do the two loops
for (CustomA__c a : myCustomA){
   for (CustomB__c b: myCustomB){
       if (a.myAText__c == b.myBText__c){
          myCount += 1;
       }
   }
}

This code does work, but it is very inefficient in terms of governor limits in Apex. We are only allowed 200,000 for the ‘Total number of executed code statements’. If we are running in batch Apex or future mode then the limit is 1,000,000. A couple of for loops like the ones above on some large lists can easily reach that number. These type of inner and outer loops produce O(n*n) (n-squared) algorithms. The Apex governor limits are trying to help us remember to be efficient about our algorithms and to try to work toward linear algorithms which can be described as O(n).

A main use for maps is to reduce the number of executed code statements and to make our code more efficient.

Let’s see how the above sample can be re-written with maps to fix this problem.

integer myCount = 0;
list myCustomA = new list();
myCustomA = [Select ID, myA__c, myAText__c From CustomA__c Where myA__c = false];

list myCustomB = new list();
myCustomB = [Select ID, myB__c, myBText__c From CustomB__c Where myB__c = false];

//Now create a map for B that we can do look-ups on.
map myBMap = new map();
for (CustomB__c b : myCustomB){
   myBMap.put(b.myBText__c, b);
}

//Now do our matching loop, but use the map instead
for (CustomA__c a: myCustomA){
  if (myBMap.containsKey(a.myAText__c){
      myCount += 1;
  }
}

There is a little overhead that is not needed in the above example because we are just trying to get a count of the matches, but the point about maps helping in the efficiency is evident. We now have a O(2n) type algorithm. We have this because we had to loop through each list once in order to find the answer, so n + n = 2n.

We could argue that the lookup within the map still takes the same amount of time as doing the actual for loop, but we are assuming that a map lookup would be more optimized. The more important part though is that the map is helping us to reduce our number of statements so we can stay away from the dreaded governor limit for the ‘Total number of executed code statements.’

The above situation may not look too bad with only two for loops, but I have run into many times where without maps there would be three or four for loops all nested inside of each other. This type of situation can quickly bring the Apex governor limits down on you without the effective use of maps.

Once you have your data in a map you can also loop through it. But you need to take advantage of the keySet method on the map, which will return a set of keys. Here is an example of retrieving into a list, converting that list to a map and then looping through the map.

list myAccounts = new list();
myAccounts = [Select ID, Name from Account limit 10];

map myAMap = new map();
for ( Account a : myAccounts ){
	myAMap.put(a.ID, a.Name);
}

for ( ID aID : myAMap.keySet() ){
	system.debug(loggingLevel.debug, myAMap.get(aID));
}

This code demonstrates that it is just as easy to loop through a map as it is to loop through a list.

I hope you have enjoyed some of these examples with maps. Get to know those maps. They are a data structure in APEX that will make your development life much easier.

Posted in: Salesforce, Software Development

Share