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);
        }
    }
} 
3
  • 2
    It throws error. - it might also be useful to post the error
    – Novarg
    May 11, 2016 at 13:40
  • Please find it updated in question. May 11, 2016 at 13:42
  • are you using a a trigger? May 11, 2016 at 13:45

3 Answers 3

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

7
  • How to reevaluate then? I need to sort List - surveyInstanceList based on mynumber=Integer.valueof(strNumber.substring(0,1)). May 11, 2016 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, 2016 at 14:02
  • @Novarg OP is asking to sort based on some integer stored in filed. How will you use compare method here? May 11, 2016 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, 2016 at 6:35
  • @Novarg yes its a text type field with multiple value and you need to parse that first. May 12, 2016 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.

4
  • if text_vod__c contains single value then we might hit list index out of bound exception. May 11, 2016 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, 2016 at 16:53
  • @sfdcfox - It throws, 'Attempt to de-reference a null object error' at this line - surveyInstanceListsorted.add(sq); May 12, 2016 at 3:11
  • Your sorted list isn't initialized. Make sure you make a initialize the list.
    – sfdcfox
    May 12, 2016 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.

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .