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?

  • sfdcfox

    sfdcfox Correct answer

    8 years ago

    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()]);
    

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM

Tags used