7.3. Traversing ArrayLists with Loops

While loops, for loops, and enhanced for each loops can all be used to traverse an ArrayList just like an array.

7.3.1. Enhanced For Each Loop

You can use a enhanced for-each loop to traverse through all of the items in a list, just like you do with an array as shown in the main method below.

coding exercise Coding Exercise

What does the following code do? Guess before you run it. Then, add another enhanced for each loop that computes the product of all the elements in myList by multiplying them and prints it out.

7.3.2. For Loop

You can also use a while or for loop to process list elements using the index. The ArrayList index starts at 0 just like arrays, but instead of using the square brackets [] to access elements, you use the get(index) to get the value at the index and set(index,value) to set the element at an index to a new value. If you try to use an index that is outside of the range of 0 to the number of elements − 1 in an ArrayList, your code will throw an ArrayIndexOutOfBoundsException, just like in arrays.

coding exercise Coding Exercise

The following code will throw an ArrayIndexOutOfBoundsException. Can you fix it?

7.3.3. While Loop

The example below demonstrates a while loop and an object-oriented approach where the list is a field of the current object and you use an object method rather than a class (static) method to loop through the list.

coding exercise Coding Exercise

What does the following code do? Guess what it does before running it. Can you change the code so that it only removes the first name it finds in the list that matches? (Hint: use the found variable).

Be careful when you remove items from a list as you loop through it. Remember that removing an item from a list will shift the remaining items to the left. Notice that the method above only increments the current index if an item was not removed from the list. If you increment the index in all cases you will miss checking some of the elements since the rest of the items shift left when you remove one.

Do not use the enhanced for each loop if you want to add or remove elements when traversing a list because it will throw a ConcurrentModificationException error. Since for each loops do not use an index, you cannot do this special case of incrementing only if it is changed. So if you are going to add or remove items or you need the index, use a regular for loop or a while loop.

exercise Check your understanding

    7-3-1: Assume that nums has been created as an ArrayList object and it initially contains the following Integer values [0, 0, 4, 2, 5, 0, 3, 0]. What will nums contain as a result of executing numQuest?

    ArrayList<Integer> list1 = new ArrayList<Integer>();
    private ArrayList<Integer> nums;
    
    // precondition: nums.size() > 0;
    // nums contains Integer objects
    public void numQuest()
    {
       int k = 0;
       Integer zero = new Integer(0);
       while (k < nums.size())
       {
          if (nums.get(k).equals(zero))
             nums.remove(k);
          k++;
       }
    }
    
  • [0, 4, 2, 5, 3]
  • Incrementing the index each time through the loop will miss when there are two zeros in a row.
  • [3, 5, 2, 4, 0, 0, 0, 0]
  • This would be true if the code moved the zeros to the end, but that is not what it does.
  • [0, 0, 0, 0, 4, 2, 5, 3]
  • This would be true if the code moved the zeros to the font, but that is not what it does.
  • [4, 2, 5, 3]
  • This would be correct if k was only incremented when an item was not removed from the list.

You can step through the code above by clicking on the following Example.

        7-3-2: The following has the correct code for the method getScore plus at least one extra unneeded code statement.  This method will calculate and return the score for a word game.  The code should loop through all of the elements in wordList and if the length of the current word is 3 it should add one to the score, if the length of the word is 4 it should add 2 to the score, and if the length is greater than 4 it should add 3 to the score.  The method should return the score.  Drag the needed blocks from the left into the correct order on the right. Check your solution by clicking on the Check Me button.  You will be told if any of the blocks are in the wrong order or if you need to remove one or more blocks.  There is one extra block that is not needed in a correct solution.public static int getScore(List wordList)
{
---
  int score = 0;

  for (String word : wordList)
  {
---
    if (word.length() == 3)
---
    {
      score++;
    }
---
    else if (word.length() == 4)
    {
      score = score + 2;
    }
---
    else if (word.length() > 4)
    {
      score = score + 3;
    }
---
  } // end for
---
  return score;

} // end method
---
if (word.length == 3) #distractor
        
        7-3-3: The following has the correct code for a method called insertInOrder plus at least one extra unneeded code statement. This method should add the passed name in alphabetic order to a private list field called nameList.  Drag the needed blocks from the left into the correct order on the right. Check your solution by clicking on the Check Me button.  You will be told if any of the blocks are in the wrong order or if you need to remove one or more blocks.  There is one extra block that is not needed in a correct solution.public void insertInOrder(String name)
{
---
  int index = 0;
---
  while (index < nameList.size() &&
         nameList.get(index).compareTo(name) < 0)
  {
---
    index++;
---
  } // end while
---
  nameList.add(index,name);
---
} // end method
---
nameList.add(name); #distractor
        

7.3.4. ArrayList of Student Objects

coding exercise Coding Exercise

You can put any kind of Objects into an ArrayList. Even objects for a class that you wrote. For example, here is an ArrayList of Students. Although the print statement works here, you may want a nicer printout. Add a loop that prints out each student and then a new line.

7.3.5. groupwork Programming Challenge : FRQ Word Pairs

This challenge is based on the 2018 Free Response Question #2 WordPair. We encourage you to work in pairs on this challenge.

You are given a class called WordPair that can store pairs of words.

class WordPair {
    private String word1;
    private String word2;

    public WordPair(String w1, String w2) {
        word1 = w1;
        word2 = w2;
    }
    public String getFirst() {
        return word1;
    }
    public String getSecond() {
        return word2;
    }
    public String toString() {
        return "(" + word1 + ", " + word2 + ")";
    }
}

First, see if you can create an ArrayList of WordPair Objects below. Look at the StudentList example above for help.

../_images/wordpairs.png

In this FRQ, you are given an array of words and you will create pairs of them by taking the first word and pairing it with all the other words, then taking the second word and pairing it with all but the first one, and so on. For example, if the word array is [“Hi”, “there”, “Tyler”, “Sam”], this figure shows how the word pairs are formed.

In the class WordPairsList below, you will write the constructor which takes the array of words and pairs them up as shown in the figure. You will need nested loops to pair each element with the rest of the elements in the list. Here is the pseudocode.

  • Initialize the allPairs list to an empty ArrayList of WordPair objects.

  • Loop through the words array for the first word in the word pair (for loop from index i = 0 to length-1)

    • Loop through the rest of the word array starting from index i+1 for the second word in the word pair (for loop from index j = i+1 to length)

      • Add the new WordPair formed from the ith word and the jth word to the allPairs ArrayList.

In the next part of the FRQ challenge, you are asked to write a method called numMatches() that counts and returns the number of pairs where the first word is the same as the second word. For example, if the word array is [“hi”,”bye”,”hi”], the pairs generated would be [“hi”,”bye”], [“hi”,”hi”], and [“bye”,”hi”]. In the second pair [“hi”,”hi”], the first word is the same as the second word, so numMatches() would return 1.

For this method, you will need a loop that goes through the ArrayList allPairs and for each WordPair in allPairs, it checks to see if its first word (using the getFirst() method) equals the second word (using the getSecond() method). If there is a match, it increments a counter which it returns at the end of the method. To test this method, add another “there” into the words array and then uncomment the call to numMatches().

7.3.6. Summary

  • ArrayLists can be traversed with an enhanced for each loop, or a while or for loop using an index.

  • Deleting elements during a traversal of an ArrayList requires using special techniques to avoid skipping elements, since remove moves all the elements down.

  • Since the indices for an ArrayList start at 0 and end at the number of elements − 1, accessing an index value outside of this range will result in an ArrayIndexOutOfBoundsException being thrown.

  • Changing the size of an ArrayList while traversing it using an enhanced for loop can result in a ConcurrentModificationException being thrown. Therefore, when using an enhanced for loop to traverse an ArrayList, you should not add or remove elements.

You have attempted of activities on this page
Next Section - 7.4. ArrayList Algorithms