CS 051 Fall 2012

Lecture 22

Arrays

Sometimes we have a lot of very similar data, and we would like to do
similar things to each datum. For example, last week we looked at a
program in which we had a bunch of balls, each of which moved a bit
to simulate a chain reaction.

In mathematics this is done by attaching subscripts to names. We can talk
about numbers n1, n2,... We want to be able to do
the same thing with computer languages. The name for this type of group of
elements is an array.

Suppose we wish to have a group of elements all of which have type
ThingAMaJig and we wish to call the group things. Then
we write the declaration of things as

    ThingAMaJig[] things;

The only difference between this and the declaration of a single item of
type ThingAMaJig is the occurrence of "[ ]" after
the type.

Like all other objects, a group of elements needs to be created:

    things = new ThingAMaJig[25];

Again, notice the square brackets. The number in parentheses (25)
indicates the maximum number of elements that there are slots for. We
can now refer to individual elements using subscripts. If, as above,
we define things to have 25 elements, they may be referred to as:

    things[0], things[1], ..., things[24]

We start numbering the subscripts at 0, and hence the last
subscript is one smaller than the total number of elements. Thus in
the example above the subscripts go from 0 to 24.

One warning: When we initialize an array as above, we only create slots
for all of the elements, we do not necessarily fill the slots with
elements. Actually, the default values of the elements of the array are
the same as for instance variables of the same type. If
ThingAMaJig is an object type, then the initial values of all
elements is null, while if it is int, then the
initial values will all be 0. Thus you will want to be
careful to put the appropriate values in the array before using them (esp.
before sending message to them!).

The program Slides, provides a slide show.

In this code excerpt there are two arrays: image is an array
of objects of type Image, while slide is an array
of type VisibleImage. Each is created to have
numSlides elements. The elements in images are
initialized individually using getImage(...), while the
elements of slide are initialized in a for loop.
For loops are frequently used with arrays since the for loop makes it easy
to cycle through all of the elments of the array.

We included buttons that allow the user to walk through the slide
show in order, either forward or backward.

There are two buttons available named next and previous:

    public void actionPerformed(ActionEvent event)  {
        slide[counter].hide();          // hide last slide
        if(event.getSource() == next) {   // get next (or previous) slide
            counter = (counter + 1) % numSlides;  // (wrapping if necessary)                     
        } else {
            counter = (counter + numSlides - 1) % numSlides;    
        }
        slide[counter].show();
    }

Notice how easy it is to move from one element to the next with an array.
Let us first take a look at what happens if the next button
is pushed. If counter starts out at 0, then slide[0] is
hidden, counter is increased by 1, and then slide[1] is shown.

The statement counter = (counter + 1) % numSlides may need a
bit of explanation. The symbol "%" represents the "mod" operator.
If m and n are ints, then m%n
represents the remainder after dividing m by n. In
the above program numSlides is 7. Clearly 1%7 = 1, 2%7 = 2, etc., but something
interesting happens for the first time when counter is 6.
When counter = (counter + 1) % numSlides is executed,
counter + 1 evaluates to 7, and 7 % numSlides is 0.
Hence if we look through the sequence of values that counter
takes on when the user clicks on the next button, we see that
it is 0, 1, 2, 3, ..., 6, 0, 1, 2, ... Thus we normally go up by 1,
but when we pass 6 the value automatically goes back to 0.

We leave as an exercise for the reader to figure out what happens when
we execute counter = (counter + numSlides - 1) % numSlides
when the previous button is clicked repeatedly. We simply
note that you might have expected to see counter = (counter - 1)
% numSlides
, but that would not work because if n is a
negative number n%m returns a non-positive number. In
particular, -1%7 evaluates to -1. In order to
force it to be positive, we always add numSlides. Try it out
by hand to see the sequence of values obtained.

A fancier drawing program

For the next example, we go back to the drawing program that we first used
as an example of using GUI components. It has choice buttons to determine
the shape of the object to be drawn (square or circle) and its color. Now
we would like to enhance the program to allow the user to click on one of
the objects on the canvas and drag it to a new position. We do that by
adding a new choice button that will allow us to choose whether we wish to
draw a new geometric object, or select an old one to drag. The drawing is
handled as before, but selecting an element used to be impossible because
once we created a new object, the variable holding the old object now only
refers to the new object, leaving the old object inaccessible. We will
now make up for that by keeping all of the entries on the screen in an array.

Demo: Drawing program

Notice the code to create a new array does not create any items in the
array. That is handled by the call of addNew in onMousePress.

We bump up the count of the number of objects after each
addition of a new element. Thus numObjects provides an
accurate count of the number of objects of the array which are really in
use. The constant maxArray simply keeps track of the total
number of available slots, not the number of slots in use.

Notice also that the first statement of the addNew method
checks to make sure that numObjects is less than
maxObjects. If we omitted that check and tried to insert
something in geomObject[maxObjects] we would get an
ArrayIndexOutOfBoundsException and your program would crash.