Using ArrayLists
This set of Mini-Lab Exercises is the fourth in a series in which students build a small program with several fish moving around in an aquarium. The set includes the following exercises:
Each section contains an Introduction to a problem or task, descriptions or examples of one or more Concepts to apply in solving the problem or completing the task, and an Exercise.
In the exercises that precede this one, students will have created three
fish that move randomly back and forth in an aquarium,
being careful not to hit the sides. Students should be familiar with basic
for loops, simple selection statements, prompting for input, and the
   java.util.Random class.
A more realistic simulation of an aquarium would have more than two or three fish. We could modify the simulation so that it supports four fish, five fish, or twelve fish in that many variables, but if we "hard-code" the number of fish into the program in this way, then we must modify and re-compile the program to change the number of fish in the aquarium. We must also repeat statements, such as the code to move fish, four, five, or twelve times.
A better alternative would be to ask the user how many fish to place
in the aquarium and then store them in a collection object. We can use
a Java ArrayList (from the java.util
package) to store the
collection of fish.
  Java provides a number of classes that provide different ways to keep
  track of a group or collection of objects.  The Java
  ArrayList class is one of these.
  An ArrayList object
  is a list of items with several important characteristics:
  
ArrayList without knowing in
      advance how many items the list will eventually hold. The syntax for creating a Java ArrayList is: 
  
ArrayList<Type> v;           // v is a potential reference to an ArrayList
v = new ArrayList<Type>();   // v now refers to a newly constructed ArrayList where the <Type> portion indicates what
  type of object the ArrayList will hold.  For example, the
  following code fragment creates an empty deck of cards:
  
ArrayList<Card> deck = new ArrayList<Card>();
| Exercise
 
 | 
Of course, we don't see any fish, because we haven't created any. But we do have a container to hold them. When we create fish, we can put them directly into the collection by adding them to the list. Once we have fish in the collection, how do we do anything with them? We can use Indexed Random Access to refer to any individual item in a list.
The add method in the ArrayList class
  adds a new item to the end of the list.
  
 For example, if deck is a Java ArrayList of playing 
    cards, then either of the following code fragments adds a new
    Card to the end of the deck: 
    
| Adding an object using a variable | Adding an object without a variable | 
|---|---|
|  |  | 
Using the style in the second example, we do not need to create 52 different variables to add 52 cards to the deck.
To access a specific item in a list directly, we specify its index.
     List indices start at 0, not at 1, so if
     there are N items in a list, the valid indices are 0 to N-1.
  The expression deck.size() indicates how many items are
  in the list (the N for that list).
    
 For example, if deck is a Java ArrayList of playing 
    cards, then we could use the following statements to display
    various cards in the deck.
    
| Card to display | Code to display it | 
|---|---|
| first card in the deck |  | 
| sixth card in the deck | (assuming that there are at least 6 cards in the deck) | 
| last card in the deck | 
 | 
Indices can also be used to modify an element in a data structure. For example, to swap the 1st and 52nd cards in the deck, the following code might be used:
Card temp = deck.get(0);         // temp refers to 1st card
deck.set(0, deck.get(51));       // 1st card is now same as 52nd card
deck.set(51, temp);              // 52nd card is now old 1st card
| Exercise
 
 
 | 
One of the reasons we switched to using a collection object 
was to avoid having to duplicate code for each fish, but we currently have three 
lines to add the three fish to the aquarium, and we would need to repeat
code to move the fish also.  This will not scale up well if we want 
to put many fish in the aquarium!  We can access all of the fish
sequentially using either of two different for loop
variations.
  There are two common Java idioms to access all the items in a
  collection using a for statement.
  
The simpler approach,
  if all you want to do is to access every item in the list,
  is a special-purpose for
  statement often known as a for each loop.
  The structure of a for each statement
  for stepping through a container of items
  is shown below.  <Type> should be replaced with the
  type of item in the container; the <variable> refers
  to a different item from the container each time through the loop.
for ( <Type> <variable> : <container> ){<repeated action>}
For example, the code fragment in Example 1 below displays all the cards in the deck from our examples above. This could be read as "For each Card instance in the deck (called cardInDeck), display the card."
Limitations of the for each structure: A for each statement can only be used when all the elements in the list are to be accessed and each element's position in the ArrayList doesn't matter. If you want to add items to or delete items from the list, replace the items in the list, or determine where in the list an object is located, then you cannot use a for each statment.
A common alternative is to use a for statement that is
    essentially a counted repetition, using the size of the collection
    as N, as in the following examples.  In both cases, the loop
    counts from 0 to N-1, since the valid indices are 0 to N-1.
    In fact, these two examples are
    equivalent, except that Example 2 creates a named reference
    (cardInDeck) to the indexed item in the list (similar
    to the for each loop).
    This generally makes
    subsequent actions using the indexed item easier to read, especially
    when there are multiple statements in the body of the loop
    referencing the indexed item.
    
| Example 1: For each loop | Example 2: For loop | Example 3: For loop using a variable for readability | 
|---|---|---|
|  |  |  | 
 Examples 2 or 3 can be used to change which items are in the
  collection.  For example, in the following code fragment,
  hand is an ArrayList of type
  Card, as is deck.  The code fragment
    uses the set method in the ArrayList class
    to replace each existing card in the hand with a new card
    obtained from the deck.
    
WARNING: Be sure to use the standard idiomfor (int i = 0; i < hand.size(); i++)hand.set(i, deck.dealACard();
(int i
              = 0; i < collection.size(); i++) to avoid
          off-by-one errors.
| Exercise
 
 
 | 
Now let's think about how to move and display all the fish for as many time steps as the user wants.
It seems clear that we will want to loop through the steps in the simulation, as we are already doing. It also seems clear that we will want to loop through all the fish. The question is:
To decide which loop gets nested inside of which, consider the following algorithmic structures in which we assume that we have 25 fish in the aquarium and we want to run the simulation 100 times.
| For each fish in the collection: Move 100 times and display the aquarium. | For each step in the simulation: Move the 25 fish once and display the aquarium. | 
We do not want the first fish to move 100 times, followed by the second fish moving 100 times, followed by the third fish moving 100 times. Instead, we want all 25 fish to move once, then all 25 fish to move again. This corresponds to the second solution above.
Another question we have to consider is where the display of the aquarium should be relative to the fish movement. Do we want to display the aquarium in the outer loop (as part of each simulation step), or in the inner loop (as part of processing each fish), or in neither loop? The following table illustrates these three options.
| For each step in the simulation: For each fish in the collection: Move, possibly changing direction. Display aquarium & fish. | For each step in the simulation: For each fish in the collection: Move, possibly changing direction. Display aquarium & fish. | For each step in the simulation: For each fish in the collection: Move, possibly changing direction. Display aquarium & fish. | 
Which behavior do you wish to implement?
| Exercise
 
 
 
 
 |