FAQ: Learn Java: Loops - Removing Elements During Traversal

This community-built FAQ covers the “Removing Elements During Traversal” exercise from the lesson “Learn Java: Loops”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Build Basic Android Apps with Java

Learn Java

FAQs on the exercise Removing Elements During Traversal

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!
You can also find further discussion and get answers to your questions over in Language Help.

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head to Language Help and Tips and Resources. If you are wanting feedback or inspiration for a project, check out Projects.

Looking for motivation to keep learning? Join our wider discussions in Community

Learn more about how to use this guide.

Found a bug? Report it online, or post in Bug Reporting

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

I spent a quite a lot of time to solve this step.
For those who have the same questions:

  • How does the machine know, that lunchContainer == lunchBox? We have this method removeAnts. In main() we are passing an argument to it (lunchContainer) and if you look above, where we set up this removeAnts method, it takes in an argument - lunchBox. I guess this is how the machine probably knows, that lunchBox and lunchContainer are the same. Those who have more knowledge and experience are more than welcome to comment my explanation.
  • No, there’s nothing wrong with Codecademys evaluation system. Watch out for those infinite loops like the lesson warns. I mean really watch out for those! If you have conditions in your code (and you have), ask yourself whether the loop will end eventually in case of both conditions. I never thought I’ll fall for that. But I did.
3 Likes

i have this same question as well. very confusing just like the exercise before this one :frowning:

I have the some question as well, I am not connecting the dots on where lunchBox came from.

same, guess it all comes down to what the line:

public static ArrayList removeAnts(ArrayList lunchBox)

means

I’m struggling myself with using variables between methods. But I think this is how it works:

lunchContainer = removeAnts(lunchContainer);

If you have “variable = method()” it sets the variable to whatever the method returns. removeAnts() returns lunchBox, so lunchContainer = lunchBox.

So I think this is how the whole thing works:

  1. lunchContainer is initialized in the main() method.
  2. The removeAnts() method is called with lunchContainer as the parameter.
  3. The removeAnts() method is set to take an ArrayList (in this case lunchContainer) as a parameter and “copy” it to a new ArrayList called lunchBox.
  4. removeAnts() removes all instances of “ant” from the lunchBox ArrayList, thanks to our awesome loops.
  5. removeAnts() returns lunchBox.
  6. Back to the main method where removeAnts() was called: lunchContainer is changed to = the updated lunchBox ArrayList (with ants removed).

I actually think this exercise has helped me more with working out how this stuff works than how loops work since loops seem much easier.

4 Likes

So i was really Struggling to understand how to do this one and decided to search else where to find a better way of it being explained… I came across a far superior way of doing it which made me wonder why we are being taught such outdated methods,

The solution i found was simply to use :

// Add your code below
lunchBox.removeIf( lunch → lunch.contains(“ant”));
return lunchBox;

which worked and passed the test, so i dont understand why we are learning the other longer syntax way, please explain.

1 Like

Based on some research, I don’t understand why the code is structured this way:

for (int i = 0; i < lunchBox.size(); i++) {
      if (lunchBox.get(i) == "ant"){
        lunchBox.remove(lunchBox.get(i));
        i--;    
      }
    }

Specifically, why would the syntax be:

lunchBox.remove(lunchBox.get(i)); 

why would it not be this:

lunchBox.remove(i);

Because I thought that the argument for the .remove() function was supposed to be an int representing the index of the ArrayList item you are supposed to be removing. In this scenario, lunchBox.get(i) would return a String, which should make .remove() error out.

So what am I missing?

2 Likes

Really glad you brought this up and it has got me very confused! Has this been brought up in a previous lesson?

Welcome back to the forums!

What are you referring to here?

In the first case which is

lunchBox.remove(lunchBox.get(i));

. The output from

luchBox.get(i)

would give you a String as you have rightfully interpreted. Upon which the whole expression becomes

lunchBox.remove(“String Value”);

. This is valid for the remove method of the ArrayList class to have and it then removes the appropriate value from the lunchBox arraylist.

In the second case

lunchBox.remove(i);

the i represents a integer and the code becomes

lunchBox.remove(2);

(the value depends on the value of i). This is also a valid syntax in the remove method of ArrayList class and so it removes the element in that particular index.

In conclusion both the syntax are valid and this is demonstrated in the lesson for remove method in the LearnJava: ArrayLists subsection of Arrays and ArrayLists section.

Good question. I believe the answer is: because this method (using removeIf) does not use a loop or iteration. The objective of the lesson is to get practice with iterating the same code for each item in the list. Looks like the removeIf code gives you a way to solve this particular problem without using a loop, but the loop method could help solve other problems as well.

That’s my Program…lunchContainer is giving the same result as lunchBox…Why confuse us then?

import java.util.ArrayList;

class Lunch {

public static ArrayList removeAnts(ArrayList lunchContainer) {
// Add your code below
int i = 0; // initialize counter

  while (i < lunchContainer.size()) {
    // if value is odd, remove value
    if (lunchContainer.get(i) == "ant"){
    	lunchContainer.remove(i);
    } else {
      // if value is even, increment counter
      i++;
    }
  }

return lunchContainer;
}

public static void main(String args) {
ArrayList lunchContainer = new ArrayList();
lunchContainer.add(“apple”);
lunchContainer.add(“ant”);
lunchContainer.add(“ant”);
lunchContainer.add(“sandwich”);
lunchContainer.add(“ant”);
lunchContainer.add(“ant”);
lunchContainer.add(“ant”);
lunchContainer = removeAnts(lunchContainer);
System.out.println(lunchContainer);

}
}

I would also like to know how lunchContainer and lunchBox are recognized as the same ArrayList containing the same elements. I read through a few of the explainations below, however something is just not making sense here for me.

Hello,

I was wondering if there was a specific reason this code is used in the explanation:

for (int i = 0; i < lst.size(); i++) {
if (lst.get(i) == “value to remove”){
// remove value from ArrayList
lst.remove(lst.get(i));
// Decrease loop control variable by 1
i–;
}
}

IMO, I think this is more complicated than it needs to be. I instead came up with this solution that worked in my IDE:

for (int i = 0; i < arrayListName.size(); i++) {
if (arrayListName.get(i) % 2 != 0) {
arrayListName.remove(i);
} else {
continue;
}
}

So, my question is: Is there any reason the first is a better way of doing things?

To preserve code formatting in forum posts, see: [How to] Format code in posts

Are you sure your proposed solution works correctly? Always a good idea to test your code with a variety of cases.

Consider the following example.

Suppose we have an ArrayList called numbers,

[1, 2, 3, 4, 5, 7, 9, 20, 3, 1, 8, 5]

and we want to remove all the odd numbers. So, the expected output is:

[2, 4, 20, 8]

Run both versions of codes and observe the output.
Remarks:

  • The remove method can be used in two ways (Java ArrayList remove())

  • I have added some print statements so that we can observe what is happening in each iteration of the loop.

Version A:

import java.util.ArrayList;

class HelloWorld {
    public static void main(String[] args) {

        int[] nums = {1, 2, 3, 4, 5, 7, 9, 20, 3, 1, 8, 5};
        
        ArrayList<Integer> numbers = new ArrayList<Integer>();
        
        for (int n: nums) {
            numbers.add(n);
        }
        
        System.out.println("Before Loop:");
        System.out.println(numbers);
        
        for (int i = 0; i < numbers.size(); i++) {
            System.out.println(String.format("Index: %s, Element at this index is: %s ", i, numbers.get(i)));
            if (numbers.get(i) % 2 != 0) {
                numbers.remove(i);
                i--;
            }
        }
        
        System.out.println("After Loop:");
        System.out.println(numbers);
    }
}

Version A Output:

Before Loop:[1, 2, 3, 4, 5, 7, 9, 20, 3, 1, 8, 5]
Index: 0, Element at this index is: 1 
Index: 0, Element at this index is: 2 
Index: 1, Element at this index is: 3 
Index: 1, Element at this index is: 4 
Index: 2, Element at this index is: 5 
Index: 2, Element at this index is: 7 
Index: 2, Element at this index is: 9 
Index: 2, Element at this index is: 20 
Index: 3, Element at this index is: 3 
Index: 3, Element at this index is: 1 
Index: 3, Element at this index is: 8 
Index: 4, Element at this index is: 5 
After Loop:
[2, 4, 20, 8]



Version B:

import java.util.ArrayList;

class HelloWorld {
    public static void main(String[] args) {

        int[] nums = {1, 2, 3, 4, 5, 7, 9, 20, 3, 1, 8, 5};
        
        ArrayList<Integer> numbers = new ArrayList<Integer>();
        
        for (int n: nums) {
            numbers.add(n);
        }
        
        System.out.println("Before Loop:");
        System.out.println(numbers);
        
        for (int i = 0; i < numbers.size(); i++) {
            System.out.println(String.format("Index: %s, Element at this index is: %s ", i, numbers.get(i)));
            if (numbers.get(i) % 2 != 0) {
                numbers.remove(i);
            } else {
                continue;
            }
        }
        
        System.out.println("After Loop:");
        System.out.println(numbers);
    }
}

Version B Output:

Before Loop:
[1, 2, 3, 4, 5, 7, 9, 20, 3, 1, 8, 5]
Index: 0, Element at this index is: 1 
Index: 1, Element at this index is: 3 
Index: 2, Element at this index is: 5 
Index: 3, Element at this index is: 9 
Index: 4, Element at this index is: 3 
Index: 5, Element at this index is: 8 
Index: 6, Element at this index is: 5 
After Loop:
[2, 4, 7, 20, 1, 8]

If we are adding or removing elements to an ArrayList while iterating over it, we have to be careful. Notice, how some elements don’t even get checked for odd/even in Version B.

1 Like

Hi, thanks for opening my eyes to that fact. Can you please also shed some insight on how to better format my code, like what is your preferred formating principle?

Hello Everyone i found that most people were struggling with why or how to do this the why being why wont it let you use shorter codes which that is because it wants you to first learn the advanced codes rather than the easy codes!

Also here is the code if you need it!

import java.util.ArrayList;

class Lunch {

public static ArrayList removeAnts(ArrayList lunchBox) {
// Using a for loop to loop through the lunchBox
for (int i = 0; i < lunchBox.size(); i++) {
String food = lunchBox.get(i);
if (food.equals(“ant”)) {
lunchBox.remove(i);
i–; // After removing an element, we need to decrement the index to prevent skipping the next element
}
}
return lunchBox;
}

public static void main(String args) {
ArrayList lunchContainer = new ArrayList();
lunchContainer.add(“apple”);
lunchContainer.add(“ant”);
lunchContainer.add(“ant”);
lunchContainer.add(“sandwich”);
lunchContainer.add(“ant”);
lunchContainer = removeAnts(lunchContainer);
System.out.println(lunchContainer);

}
}

Guys, why does the while loop still need the increment of the counter variable? It says in the course that

When using a while loop and removing elements from an ArrayList, we should not increment the while loop’s counter whenever we remove an element. We don’t need to increase the counter because all of the other elements have now shifted to the left.

import java.util.ArrayList;

class Lunch {
 
  public static ArrayList<String> removeAnts(ArrayList<String> lunchBox) {
    // Add your code below
    int i = 0;
   while(i < lunchBox.size()) {
    if(lunchBox.get(i) == "ant") {
      lunchBox.remove(lunchBox.get(i));
    } else {
      i++;
    }
   }
  return lunchBox;
  }
 
  
  public static void main(String[] args) {
    ArrayList<String> lunchContainer = new ArrayList<String>();
    lunchContainer.add("apple");
    lunchContainer.add("ant");
    lunchContainer.add("ant");
    lunchContainer.add("sandwich");
    lunchContainer.add("ant");
    lunchContainer = removeAnts(lunchContainer);
    System.out.println(lunchContainer);

  }
}

In a for loop, the loop variable will be automatically incremented/decremented (depending on how we have written the loop) once we reach the end of the iteration.

A while loop will NOT automatically update the loop variable. It is our responsibility to update the loop variable (If there is no statement within the body of the while loop which updates the loop variable, we are likely to end up in an infinite loop).

The excerpt you have posted is saying that there is no i++; statement necessary inside the if block. When we remove an element from the lunchBox ArrayList, all the remaining elements (that we haven’t iterated over yet) will be shifted one place left. Suppose the element at index 2 is "ant" and the element at index 3 is "sandwich". If currently i is 2 and we remove "ant" from the ArrayList, then we don’t need to do anything to i. In the next iteration, i will still be 2 but "sandwich" is no longer at index 3 but has shifted to index 2.
However, if the if condition is not true, then we must manually increment i in the else block. The while loop will not automatically increment the loop variable. We must do so ourselves.

Instead of

why does the while loop still need the increment of the counter variable?

perhaps a more apt question would be why does the if block not need an increment statement. Suppose we weren’t removing elements from the ArrayList and doing something different in the if block (like printing some phrase instead of removing the element), then we would need i++; in the if block as well to make sure that the loop variable is incremented before the next iteration lest we get stuck in an infinite loop.

1 Like