16

In apex, how can I remove an element from a list being looped?

List<String> companyinfos=new List<String>();
companyinfos.add('a1');
companyinfos.add('a2');
companyinfos.add('a3');
companyinfos.add('b1');
companyinfos.add('b2');

integer index=0;
For(String s: companyinfos)
{
    if(s.contains('a')){
        companyinfos.remove(index);
        index--;
    }
index++;
}  


System.debug(companyinfos);  

ERROR: Cannot modify a collection while it is being iterated.

7 Answers 7

36

As long as you don't use the shorthand iteration technique for(Object a : Objects) and use a traditional for loop, it works fine (you must traverse the list in reverse order as the example shows)

Try this:

for (Integer i = (companyinfos.size()-1) ; i>= 0 ; i--){
    String s = companyInfos[i];
    if(s.contains('a')){
        companyinfos.remove(i);
    }
} 
1
  • 15
    Note that looping in reverse order is essential because otherwise, if you remove an item and the list gets shoter, you'll get an index out of bound exception if you try to fetch item past the end of the list. Commented May 22, 2017 at 9:43
7

Salesforce prohitbits (or at least used to do that earlier) removing items from list while traversing it.

So, the solution would be to create another list, store all desired elements in there. For e.g.

List<CompanyInfo> companyinfos=new List<companyinfos>();
List<CompanyInfo> finalList=new List<companyinfos>();
companyinfos.add(***);
....

integer index=0;
For(CompanyInfo info: companyinfos)
{

    if(info.item!=****)
    {
        finalList.add(info);
    }
}  
companyinfos = finalList;
0
4

Using While loop to remove an element from a list while being looped

If you want to remove an element in a list by checking for a specific condition, you can use while loop instead of for loop. By doing so, you could remove element from list using index.

Here is the sample code to do so

Integer i = 0;
while (i < companyinfos.size()){
    if(companyinfos.get(i).contains('a')){
        companyinfos.remove(i);
    } else {
        i++;
    }
}
4
  • this does not work as the act of removing shifts the remaining elements to one lower array index value. For example, if all companies contain a, you'll retain the second, fourth, sixth, ... entries.
    – cropredy
    Commented Jun 10, 2019 at 20:08
  • @cropredy This does work and its a tested code. Because even though the array index shifts, the index only increments when it doesn't find a match and if a match is found, it won't increment the index, hence it covers that scenario. Commented Jun 11, 2019 at 5:36
  • Hmmm. When I did this, I had diff results. I'll check my work again. Sorry
    – cropredy
    Commented Jun 11, 2019 at 13:01
  • No problem @cropredy :) Appreciate your suggestions and corrections on posts. Commented Jun 11, 2019 at 13:26
0

First You should find the index of that letter from companyinfos list the remove that index Try this and let me Know

for (Integer i = (companyinfos.size()-1) ; i>= 0 ; i--)
{
    if(companyinfos.contains('a')){
    Integer index =companyinfos.indexOf('a');
    companyinfos.remove(index);
    }
} 
0

you dont have to remove using indexes. Just add needed the elements into another list.

List<String> companyinfos = new List<String>();
List<String> newCompanyinfos = new List<String>();

companyinfos.add('a1');
companyinfos.add('a2');
companyinfos.add('a3');
companyinfos.add('b1');
companyinfos.add('b2');

for(String s:companyinfos){
    if(!s.contains('a')){
        newCompanyinfos.add(s); // you will get new list without As
    }
}
0

It is not possible to use delete/remove operation using short-hand iteration so there are many other ways by which you could achieve this.

So here is a forward approach that is when you delete any element then the list get shortened so for this you don't need to increment the index.

Using for loop:

List<String> companyInfos = new List<String>{'a1', 'a2', 'a3', 'b1', 'b2'};

for(Integer index = 0; index < companyInfos.size();)
    if(companyInfos[index].contains('a'))
         companyInfos.remove(index);
    else
        index++;

System.debug(companyInfos);

And you can also use using While loop:

List<String> companyInfos = new List<String>{'a1', 'a2', 'a3', 'b1', 'b2'};

Integer index = 0;
while(index < companyInfos.size())
    if(companyInfos[index].contains('a'))
        companyInfos.remove(index);
    else
        index++;

System.debug(companyInfos);
1
  • 1
    This answer doesn't appear to offer any new information.
    – Derek F
    Commented Feb 23, 2023 at 12:14
-2

In Java it's agood practice to use the iterator when removing something from a list being looped:

List<String> companyinfos=new List<String>();
companyinfos.add('a1');
companyinfos.add('a2');
companyinfos.add('a3');
companyinfos.add('b1');
companyinfos.add('b2');

Iterator<String> it = companyinfos.iterator();

while(it.hasNext()){

String next = it.next();

if(next.contains('a')){
  it.remove();
}

}
1
  • 2
    Apex is not Java, although they share behaviors extensively. If this solution also applies to Apex, please edit to clarify that.
    – David Reed
    Commented May 28, 2020 at 15:00

You must log in to answer this question.

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