0

I have below code where I need to modify the List during iteration. It throws error. can someone suggest a way out in this case? **Error **

System.FinalException: Cannot modify a collection while it is being iterated.

Apex Code

for(Survey_Question_vod__c  sq: surveyInstanceList )
{
    if(sq.text_vod__c!=null)
    {
        String formattedStr =sq.text_vod__c;
        String[] strArr = formattedStr.split(' ');
        strNumber = strArr[1];
        mynumber=Integer.valueof(strNumber.substring(0,1));
        If(mynumber==count)
        {
            surveyInstanceListsorted.add(sq);
            count++;
        }
        else
        {
            surveyInstanceList.add(sq);
        }
    }
} 
  • 2
    It throws error. - it might also be useful to post the error – Novarg May 11 '16 at 13:40
  • Please find it updated in question. – Testing_SFDC May 11 '16 at 13:42
  • are you using a a trigger? – Pranay Jaiswal May 11 '16 at 13:45
2

The error that you get is pretty self-explanatory: Cannot modify a collection while it is being iterated.

What you should do instead, is create a new list and fill it instead. For example:

List<Survey_Question_vod__c> tempList = new List<Survey_Question_vod__c>();
for (Survey_Question_vod__c sq :surveyInstanceList) {
    // Your code, but replace surveyInstanceList.add(sq); with:
    tempList.add(sq);
}

EDIT

If you want to sort this list based on some criteria, you should actually write a wrapper class that implements Comparable interface. After that you can simply sort this list with a one-liner:

surveyInstanceList.sort();

For more info check this page

|improve this answer|||||
  • How to reevaluate then? I need to sort List - surveyInstanceList based on mynumber=Integer.valueof(strNumber.substring(0,1)). – Testing_SFDC May 11 '16 at 13:49
  • @SFDC_Learner if you want to sort it you should actually write a wrapper class that implements Comparable interface and global Integer compareTo() method and then simply run surveyInstanceList.sort() – Novarg May 11 '16 at 14:02
  • @Novarg OP is asking to sort based on some integer stored in filed. How will you use compare method here? – Tushar Sharma May 11 '16 at 16:17
  • @TusharSharma sort based on some integer? As far as I know, comparing integers is not a problem, just use > or < operators – Novarg May 12 '16 at 6:35
  • @Novarg yes its a text type field with multiple value and you need to parse that first. – Tushar Sharma May 12 '16 at 6:51
2

If you really want to use in-place sorting, you might do this:

for(Integer index = 0; index < surveyInstanceList.size(); index++) {
    Survey_Question_vod__c  sq = surveyInstanceList[index];
    if(sq.text_vod__c!=null) {
        If(Integer.valueof(sq.text_vod__c.split(' ')[1].left(1)) == count) {
            surveyInstanceListsorted.add(sq);
            count++;
        } else {
            // -- will step back one to process record that just moved in
            surveyInstanceList.add(surveyInstanceList.remove(index--));
        }
    }
} 

As long as you don't try to modify a collection that's currently being iterated, you're okay. This example works around that by using indices. Also note that we remove the current record as we add it to the end, so that our list won't keep growing in size as we continue.

|improve this answer|||||
  • if text_vod__c contains single value then we might hit list index out of bound exception. – Tushar Sharma May 11 '16 at 16:28
  • 2
    @TusharSharma And the value might not parse into an Integer value, either. And count might go above 9, which means this would then spiral into an infinite loop. Etc... there's other things that the poster will need to overcome, but this answer was focused simply on the technique to modify a collection in place. – sfdcfox May 11 '16 at 16:53
  • @sfdcfox - It throws, 'Attempt to de-reference a null object error' at this line - surveyInstanceListsorted.add(sq); – Testing_SFDC May 12 '16 at 3:11
  • Your sorted list isn't initialized. Make sure you make a initialize the list. – sfdcfox May 12 '16 at 3:13
0

No you cannot do the modification to the collection item currently being iterated. To do modification(addition/deletion of elements) use another collection element inside the iteration.

List<Survey_Question_vod__c> surveyInstanceListUpdate = new List<Survey_Question_vod__c>();
for(Survey_Question_vod__c  sq: surveyInstanceList )
{
    if(sq.text_vod__c!=null)
    {
        String formattedStr =sq.text_vod__c;
        String[] strArr = formattedStr.split(' ');
        strNumber = strArr[1];
        mynumber=Integer.valueof(strNumber.substring(0,1));
        If(mynumber==count)
        {
            surveyInstanceListsorted.add(sq);
            count++;
        }
        else
        {
            //surveyInstanceList.add(sq); // use another list of Survey_Question_vod__c instead of list being iterated
            surveyInstanceListUpdate.add(sq);
        }
    }
}

Hope it helps.

|improve this answer|||||
  • For values in surveyInstanceListUpdate List, I have to reevaluate with If(mynumber==count). Basically I need to sort surveyInstanceList. That's it. – Testing_SFDC May 11 '16 at 13:47
  • How to reevaluate then? I need to sort List - surveyInstanceList based on mynumber=Integer.valueof(strNumber.substring(0,1)). – Testing_SFDC May 11 '16 at 13:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.