Using Arrays and Collections in Java SE 7
This article is based on his book Oracle Certified Associate, Java SE 7 Programmer Study Guide by Richard Resse released in August 2012 by Packt Publishing. The book provides an in-depth understanding of Java through the examination of objects and methods, extensive code examples and and coverage of good programming and design practices as they relate to the certification objectives
—
This article, when boiled down to its essence, is about data structures. Specifically, it is about arrays—the java.util.Arrays and java.util.ArrayList classes. An array is a region of memory that can be addressed using a single variable name. It provides an efficient technique for accessing data in a sequential or random fashion. The Arrays class provides support for arrays while the ArrayList class provides array-like behavior but is not fixed in size.
We are concerned with how to create and use these data structures. A common operation is the traversal of an array or collection. We will see that Java supports several approaches permitting us to move through the elements of an array or an ArrayList object. Common to both arrays and collections is the ability to use the for-each statement. Iterators provide an alternate approach for accessing collections such as the ArrayList, and will also be discussed.
We will start by examining arrays in detail. This will include the creation and use of single and multidimensional arrays. Common array operations such as copying and sorting will be demonstrated.
As arrays are a simple data structure, most languages do not provide much support for operations on them. The java.util.Arrays class fills this void and supports important operations against arrays. These include copying, filling, and sorting the arrays.
The java.util package contains a number of interfaces and classes that can make working with collections of data easier. In this chapter we will examine the use of iterators and the ArrayList class which are part of this package. Iterators provide a technique for traversing over collections which can be very useful. The ArrayList class is frequently used instead of arrays when the size of the collection may change. It provides a number of valuable methods for the modification of collections.
We will also examine how to encapsulate a collection, such as the ArrayList, in another class.
Arrays
An array allows multiple values to be accessed using a single variable name. Each element of an array is of the same type. The element type can be a simple primitive data type or a reference to an object.
One-dimensional arrays are allocated to a contiguous region of memory. This means that the elements of the array can be accessed efficiently as they are adjacent to each other. Arrays use an integer index to access an element in the array. Indexes range from 0 to the length of the array minus one. We are able to access the elements of
an array directly, in any order as needed by the application, without having to visit each element.
Though Java supports multidimensional arrays, one-dimensional arrays are most commonly used. Arrays can be used for a variety of purposes including:
• A collection of numbers representing ages
• A list of employee names
• A list of prices for an item in a store
The main disadvantage of arrays is that they have a fixed size. This makes it more difficult and less efficient to add, remove, or resize any list or collection of data represented by an array.
Our discussion will begin with the coverage of one-dimensional and multidimensional arrays. This is followed by discussions of common array techniques such as traversing an array and copying arrays. In the firsttwo sections, we will use simple “for loops” to traverse array elements. Alternative methods are covered in the Traversing arrays section.
One-dimensional arrays
A one-dimensional array is intended to represent a simple linear list. The following code snippet illustrates the declaration and use of a one-dimensional array. The array, ages, is declared in the first statement as an array of the int type. In the second statement, memory is allocated for the array using the new operator. In this example, the array consists of 5 elements:
[java]
int[] ages;
ages = new int[5];
[/java]
The ages array has 5 elements allocated to it. The first index of any array is 0. The largest index of an array is its length – 1. Thus, the last index of the array is 4. A runtime exception will be generated if an index used is outside the legal range of values for an array. The array could have been declared and created using a single statement, shown as follows:
[java]
int[] ages = new int[5];
[/java]
As an array name is a reference to an array, it is possible to assign a different array to the variable later in the program. We will demonstrate this later in the discussion.
An array is an object that is allocated from an area of memory known as the heap. The heap and program stack were introduced in the Stack and heap section in Chapter
2, Java Data Types and Their Usage. In the following example, the first element of ages
is assigned the value 35 and then displayed:
[java]
ages[0] = 35; System.out.println(ages[0]);
[/java]
Arrays possess the length property that returns the number of elements in the array. When the next code sequence is executed, it will return 5. Notice that length is not a method:
[java]
int length = ages.length; System.out.println(length);
[/java]
Arrays are represented in Java as objects. In the previous example, ages is an object reference variable which references the array that has been allocated to the heap. This is illustrated in the following diagram:
35
0
0
0
0
main
ages
In this example, each element of the array was initialized to 0, by default, and then the first element was assigned a value of 35.
Any attempt to use an index that is outside the bounds of the array will generate a java.lang. ArrayIndexOutOfBoundsException exception.
The placement of array brackets
There is a second option with regards to the placement of brackets when declaring an array. We can also place the brackets after the name of the array, shown as follows:
[java]
int ages[];
[/java]
To the compiler, this is equivalent to the previous declaration. However, the placement of brackets with other uses of an array name is restricted. For example, we have to place the brackets after the array name when we are declaring or referencing elements of the array. If we attempt the following when declaring an array:
[java]
ages = new [5]int;
[/java]
We will get a syntax error as follows:
expected
‘;’ expected
Likewise, if we try to use the brackets before the array name when referencing an element of the array, such as follows:
[0]ages = 0;
We get the following syntax error message:
illegal start of expression incompatible types
required: int[]
found: int
It is more common to see brackets used after the data type of the array. For example, most IDEs will at some point generate a main method. It frequently appears below with the brackets following the data type:
[java]
public static void main(String[] args) {
…
}
[/java]
Also, consider the declaration:
[java]
int[] arr1, arr2;
[/java]
Both arr1 and arr2 are declared as arrays. This is a simpler way of declaring more than one array on a single line. However, it can be argued that the following is a better format as it is more explicit:
[java]
int arr1[], arr2[];
[/java]
It can be also argued that declaring more than one variable on a line is a bad form. The best way of declaring these two arrays is as follows:
[java]
int[] arr1;
int[] arr2;
[/java]
Initializing arrays
The elements of an array are initialized to default values as shown in the following table. This table is duplicated from the Initializing identifiers section of Chapter 2, Java Data Types and Their Usage, for your convenience:
Data type Default value (for fields)
boolean false
byte 0
char ‘u0000’
short 0 int 0 long 0L float 0.0f double 0.0d String (or any object) null
In the previous example, we assigned a value of 35 to the first element of the array. This is a simple, yet tedious way of initializing the array to values other than the default value.
An alternate technique is to use a block statement to initialize the array. This is illustrated in the following example, where ages is initialized to five different
values. It is not necessary to specify the array size when using the block statement to initialize an array:
[java]
int ages[] = {35, 10, 43, -5, 12};
[/java]
A syntax error will be generated if you try to specify the size of the array, shown as follows:
[java]
int ages[5] = {35, 10, 43, -5, 12};
[/java]
The message will appear as follows:
‘]’ expected
‘;’ expected
If we want to display the content of an array, there are several methods available. Here, we will use simple indexes and the length property. In the Traversing arrays section we will demonstrate other techniques.
The following code sequence shows the difference between using the toString
method and a for loop to display an array:
[java]
int ages[] = {35, 10, 43, -5, 12}; System.out.println(ages.toString());
for(int i = 0; i < ages.length; i++) { System.out.println(ages[i]); } [/java] When executed, we get the following output: [I@27341e11
35
10
43
-5
12
Notice the use of the toString method does not return the contents of the array. Rather, it returns a strange representation of the array. We have no control over the string returned by the toString method. However,the for loop gives us what we expected.
Remember that arrays in Java always begin with an index of 0.
Instead of hard coding the size of the array as 5, as we did in an earlier example, a better approach is to use a constant. For example, the entire sequence could be rewritten as follows:
[java]
static final int SIZE = 5;
int ages[] = new int[SIZE];
// initialize ages as needed
for(int i = 0; i < ages.length; i++) { System.out.println(ages[i]); } [/java]
Use named constants for array sizes. However, using the length attribute once the array is declared is preferred, as it is more maintainable should the array size change.