The Basics of Arrays in Java: Creating An Array
The Basics of Arrays in Java: Creating An Array
Module 2: Arrays
The Basics of Arrays in Java
Creating an Array
As we noted in Module 1, there are two kinds of data in Java: primitive types (such as int and double), and objects. In
many programming languages (even object-oriented ones like C++) arrays are a primitive type, but in Java they're treated
as objects.
Accordingly you must use the new operator to create an array:
int[] intArray; // defines a reference to an array
intArray = new int[100]; // creates the array, and
// sets intArray to refer to it
The [] operator is the sign to the compiler we're naming an array object and not an ordinary variable. You can also use an
alternative syntax for this operator, placing it after the name instead of the type:
int intArray[] = new int[100]; // alternative syntax
However, placing the [] after the int makes it clear that the [] is part of the type, not the name.
Because an array is an object, its name— intArray in the code above—is a reference to an array; it's not the array itself.
The array is stored at an address elsewhere in memory, and intArray holds only this address.
Arrays have a length field, which you can use to find the size, in bytes, of an array:
int arrayLength = intArray.length; // find array length
Remember that this is the total number of bytes occupied by the array, not the number of data items you have placed in it.
As in most programming languages, you can't change the size of an array after it's been created.
Accessing Array Elements
Array elements are accessed using square brackets. This is similar to how other languages work:
temp = intArray[3]; // get contents of fourth element of array
intArray[7] = 66; // insert 66 into the eighth cell
Remember that in Java, as in C and C++, the first element is numbered 0, so that the indices in an array of 10 elements run
from 0 to 9.
If you use an index that's less than 0 or greater than the size of the array less 1, you'll get the "Array Index Out of Bounds"
runtime error. This is an improvement on C and C++, which don't check for out-of-bounds indices, thus causing many
program bugs.
Initialization
Unless you specify otherwise, an array of integers is automatically initialized to 0 when it's created. Unlike C++, this is true
even of arrays defined within a method (function). If you create an array of objects, like this:
autoData[] carArray = new autoData[4000];
then, until they're given explicit values, the array elements contain the special null object. If you attempt to access an array
element that contains null, you'll get the runtime error "Null Pointer Assignment." The moral is to make sure you assign
something to an element before attempting to access it.
You can initialize an array of a primitive type to something besides 0 using this syntax:
int[] intArray = { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27 };
Perhaps surprisingly, this single statement takes the place of both the reference declaration and the use of new to create the
array. The numbers within the curly braces are called the initialization list. The size of the array is determined by the
number of values in this list.
An Array Example
Let's look at some example programs that show how an array can be used. We'll start with an old-fashioned procedural
version, and then show the equivalent objectoriented approach. Listing 2.1 shows the old-fashioned version, called
array.java.
Listing 2.1 array.java
// array.java
// demonstrates Java arrays
////////////////////////////////////////////////////////////////
class ArrayApp
Module 2: Arrays
Data Structures and Algorithms in Java 2
{
public static void main(String[] args) throws IOException
{
int[] arr; // reference
arr = new int[100]; // make array
int nElems = 0; // number of items
int j; // loop counter
int searchKey; // key of item to search for
//-------------------------------------------------------------
//-------------------------------------------------------------
//-------------------------------------------------------------
//-------------------------------------------------------------
//-------------------------------------------------------------
} // end main()
} // end class ArrayApp
In this program, we create an array called arr, place 10 data items in it, search for the item with value 66 display all the
items, remove the item with value 55, and then display the remaining nine items. The output of the program looks like this:
77 99 44 55 22 88 11 0 66 33
Found 66
77 99 44 22 88 11 0 66 33
The data we're storing in this array is type int. We've chosen a primitive type to simplify the coding. Generally the items
stored in a data structure consist of several fields, so they are represented by objects rather than primitive types. We'll see
an example of this toward the end of this module.
Insertion
Inserting an item into the array is easy; we use the normal array syntax
arr[0] = 77;
We also keep track of how many items we've inserted into the array with the nElems variable.
Searching
Module 2: Arrays
Data Structures and Algorithms in Java 3
The searchKey variable holds the value we're looking for. To search for an item, we step through the array, comparing
searchKey with each element. If the loop variable j reaches the last occupied cell with no match being found, then the
value isn't in the array.
Appropriate messages are displayed: "Found 66" or "Can't find 27."
Deletion
Deletion begins with a search for the specified item. For simplicity we assume (perhaps rashly) that the item is present.
When we find it, we move all the items with higher index values down one element to fill in the "hole" left by the deleted
element, and we decrement nElems. In a real program, we'd also take appropriate action if the item to be deleted could not
be found.
Display
Displaying all the elements is straightforward: we step through the array, accessing each one with arr[j] and displaying it.
Program Organization
The organization of array.java leaves something to be desired. There is only one class, ArrayApp, and this class has only
one method, main(). The program is essentially an old-fashioned procedural program. Let's see if we can make it easier to
understand (among other benefits) by making it more object-oriented.
We're going to provide a gradual introduction to an object-oriented approach, using two steps. In the first, we'll separate the
data storage structure (the array) from the rest of the program. This remaining part of the program will become a user of the
structure. In the second step, we'll improve the communication between the storage structure and its user.
Dividing a Program into Classes
The array.java program essentially consisted of one big method. We can reap many benefits by dividing the program into
classes. What classes? The data storage structure itself is one candidate, and the part of the program that uses this data
structure is another. By dividing the program into these two classes we can clarify the functionality of the program, making
it easier to design and understand (and in real programs to modify and maintain).
In array.java we used an array as a data storage structure, but we treated it simply as a language element. Now we'll
encapsulate the array in a class, called LowArray. We'll also provide class methods by which objects of other classes (the
LowArrayApp class in this case) can access the array. These methods allow communication between LowArray and
LowArrayApp.
Our first design of the LowArray class won't be entirely successful, but it will demonstrate the need for a better approach.
The lowArray.java program in Listing 2.2 shows how it looks.
Listing 2.2 The lowArray.java Program
// lowArray.java
// demonstrates array class with low-level interface
////////////////////////////////////////////////////////////////
class LowArray
{
private double[] a; // ref to array a
////////////////////////////////////////////////////////////////
class LowArrayApp
{
public static void main(String[] args)
{
LowArray arr; // reference
arr = new LowArray(100); // create LowArray object
Module 2: Arrays
Data Structures and Algorithms in Java 4
//-------------------------------------------------------------
//-------------------------------------------------------------
if(j == nElems) // no
System.out.println("Can't find " + searchKey);
else // yes
System.out.println("Found " + searchKey);
//-------------------------------------------------------------
// delete value 55
for(j=0; j<nElems; j++) // look for it
if(arr.getElem(j) == 55)
break;
//-------------------------------------------------------------
} // end main()
} // end class LowArrayApp
The output from this program is similar to that from array.java, except that we try to find a non-existent key value (26)
before deleting the item with the key value 55:
77 99 44 55 22 88 11 0 66 33
Can't find 26
77 99 44 22 88 11 0 66 33
Module 2: Arrays
Data Structures and Algorithms in Java 5
low-level operations it did in the non-class version of an array in the array.java program. The only difference was that it
related to setElem() and
getElem() instead of the [] operator. It's not clear that this is an improvement.
Also notice that there's no convenient way to display the contents of the array. Somewhat crudely, the LowArrayApp class
simply uses a for loop and the getElem() method for this purpose. We could avoid repeated code by writing a separate
method for lowArrayApp that it could call to display the array contents, but is it really the responsibility of the
lowArrayApp class to provide this method?
Thus lowArray.java demonstrates how you can divide a program into classes, but it really doesn't buy us too much in
practical terms. Let's see how to redistribute responsibilities between the classes to obtain more of the advantages of OOP.
In the lowArray.java program, the main() routine in the LowArrayApp class, the user of the data storage structure must
keep track of the indices to the array. For some users of an array who need random access to array elements and don't mind
keeping track of the index numbers, this arrangement might make sense. For example, sorting an array, as we'll see in the
next module, can make efficient use of this direct "hands-on" approach.
However, in a typical program the user of the data storage device won't find access to the array indices to be helpful or
relevant. In the Cardfile program in Module 1, for example, if the card data were stored in an array, and you wanted to
insert a new card, it would be easier not to have to worry about exactly where in the array it is going to go.
The highArray.java Example
Our next example program shows an improved interface for the storage structure class, called HighArray. Using this
interface, the class user (the HighArrayApp class) no longer needs to think about index numbers. The setElem() and
getElem() methods are gone, replaced by insert(), find(), and delete(). These new methods don't require an index
number as an argument, because the class takes responsibility for handling index numbers. The user of the class
(HighArrayApp) is free to concentrate on the what instead of the how: what's going to be inserted, deleted, and accessed,
instead of exactly how these activities are carried out.
Figure 2.4 shows the HighArray interface and Listing 2.3 shows the highArray.java program.
// highArray.java
// demonstrates array class with high-level interface
////////////////////////////////////////////////////////////////
class HighArray
{
private double[] a; // ref to array a
//----------------------------------------------------------
//----------------------------------------------------------
//----------------------------------------------------------
Module 2: Arrays
Data Structures and Algorithms in Java 6
//----------------------------------------------------------
else // found it
{
for(int k=j; k<nElems; k++) // move higher ones down
a[k] = a[k+1];
nElems--; // decrement size
return true;
}
} // end delete()
//----------------------------------------------------------
//----------------------------------------------------------
////////////////////////////////////////////////////////////////
class HighArrayApp
{
public static void main(String[] args)
{
int maxSize = 100; // array size
if( arr.find(searchKey) )
System.out.println("Found " + searchKey);
else
System.out.println("Can't find " + searchKey);
The HighArray class is now wrapped around the array. In main(), we create an array of this class and carry out almost the
same operations as in the lowArray.java program: we insert 10 items, search for an item—one that isn't there—and display
the array contents. Because it's so easy, we delete three items (0, 55, and 99) instead of one, and finally display the contents
again. Here's the output:
77 99 44 55 22 88 11 0 66 33
Can't find 35
77 44 22 88 11 66 33
Module 2: Arrays
Data Structures and Algorithms in Java 7
Notice how short and simple main() is. The details that had to be handled by main() in lowArray.java are now handled by
HighArray class methods.
In the HighArray class, the find() method looks through the array for the item whose key value was passed to it as an
argument. It returns true or false, depending on whether it finds the item or not.
The insert() method places a new data item in the next available space in the array. A field called nElems keeps track of
the number of array cells that are actually filled with data items. The main() method no longer needs to worry about how
many items are in the array.
The delete() method searches for the element whose key value was passed to it as an argument, and when it finds it, shifts
all the elements in higher index cells down one cell, thus writing over the deleted value; it then decrements nElems.
We've also included a display() method, which displays all the values stored in the array.
Module 2: Arrays