How to code more efficient to avoid “Apex CPU time limit exceeded”?

I have a Web Service class. When I call the method from this class, I get “Apex CPU time limit exceeded” error. The for loops are causing this trouble. Here’s my not efficient code:

List<Task> tasks = [SELECT Id, WhoId FROM Task];
List<Contact> contacts = [SELECT Id FROM Contact];

for (Task t : tasks){
    for(Contact c : contacts){
        if (t.WhoId == c.Id){
            //some logic here   
        } 
    }
}

This piece of code matches the related Task and Contact objects. How to make it more efficient? Is there a way to reduce the number of loops here to one?

Answer

Use a Map instead:

List<Task> tasks = [SELECT Id ... FROM Task];
Map<Id, Contact> contacts = new Map<Id, Contact>([SELECT Id ... FROM Contact]);

for (Task t : tasks){
    Contact c = contacts.get(t.WhoId);
    if(c != null) {
        //some logic here   
    }
}

This technique was originally used to avoid script limits, and it’s equally effective to avoid timeout limits.

Edit

As stated by Mike, you should make sure your filters are also correctly limiting records to avoid heap limits and query limits, and your field list should include only the fields necessary to complete the task.

Task[] tasks = [SELECT Id ... FROM Task WHERE ...];
Map<Id, Contact> contacts = new Map<Id, Contact>();
for(Task record: tasks) {
    if(record.WhoId != null && record.WhoId.getSObjectType() == Contact.SObjectType) {
        contacts.put(record.WhoId, null);
    }
}
contacts.putAll([SELECT Id ... FROM Contact WHERE Id IN :contacts.keySet()]);

Attribution
Source : Link , Question Author : justasd , Answer Author : sfdcfox

Leave a Comment