CMPS 144
Introduction to the ArrayList and Comparison with Arrays
Instances of the
java.util.ArrayList class are similar to arrays but provide more
flexibility/convenience.
Similarities
Both (one-dimensional) arrays and ArrayLists are for the purpose of
storing and manipulating (linear) lists of elements "indexed by" a
consecutive range of natural numbers, starting at zero.
That is, an element in such a list is referred by its position
within that list.
Both arrays and ArrayLists can be "iterated over" using Java's
for-each loop. The examples below illustrate its use.
On successive iterations of the loop, the variable num
assumes the values of the elements indexed by 0, 1, 2, etc.
/* Returns the sum of the elements
** of the given array.
*/
public static int sumOf(int[] ary) {
int sumSoFar = 0;
for (int num : ary) {
sumSoFar = sumSoFar + num;
}
return sumSoFar;
}
|
/* Returns the sum of the elements
** of the given ArrayList.
*/
public static int sumOf(ArrayList<Integer> aryList) {
int sumSoFar = 0;
for (Integer num : aryList) {
sumSoFar = sumSoFar + num;
}
return sumSoFar;
}
|
Differences
- Size/Length: An array, once created, is fixed in length.
Thus, for example, evaluation of the expression new int[25]
results in the creation of an array having length 25, once and for all.
Upon creation, each element's value is initialized to the default value
of its type.1
The length of an array ary is provided by the expression
ary.length. (Thus, you can think of an array as being
an object having a public instance variable named length.)
An ArrayList, on the other hand, has a size that changes as
elements are inserted and removed from it. The size of an ArrayList
aryList is given by the expression aryList.size().
(Indeed, size() is an observer method of the class
ArrayList.)
- Generics: The ArrayList class has a generic type
parameter by which a client specifies, when creating an instance
of that class, the data type of the elements to be stored in it.
Thus, for example, the following are sensible variable declarations
(and object creations/assignments):
ArrayList<Integer> listOfInts = new ArrayList<Integer>();
|
ArrayList<Temperature> listOfTemps = new ArrayList<Temperature>(10);
|
ArrayList<BoundedCounter> listOfCounts = new ArrayList();
|
(Here we are assuming that the classes Temperature and
BoundedCounter are accessible to the class in which the
code above appears. The class java.lang.Integer is
the so-called wrapper class for the int data type
and is always accessible.)
In the second line, the 10 was included, optionally, to provide
an estimate of the needed size of the ArrayList. It does not, however,
impose an upper bound upon the size to which the structure can grow.
In the third line, the expression that creates the ArrayList fails to
indicate that the intended data type of its elements is
BoundedCounter. That's because Java infers this from the
variable declaration and thus repeating it is optional.
- Data Type of Elements:
An array's elements can be of any data type.
Elements in an ArrayList are restricted to be of a reference
(i.e., non-primitive) type, however. Thus, for example, in declaring
a variable whose purpose is to refer to an ArrayList containing integers,
you would use a declaration such as
ArrayList<Integer> listOfInts;
that refers to the wrapper class Integer rather than
to the primitive type int. (Luckily, in many contexts you
can use expressions of types int and Integer
interchangably due to Java's
autoboxing
and unboxing features.)
As is the case with other generic Java classes, if you fail to
provide a type parameter when declaring a variable to be of type
ArrayList, it is as though you had provided Object.
For example, the declaration/initialization
ArrayList listOfObjs = new ArrayList();
would make sense if you intended for listOfObjs to be a
heterogeneous ArrayList (meaning one that stores (references to)
objects of various types).
- Element Retrieval:
The elements in both arrays and ArrayLists are indexed by a range of
integers starting at zero. To retrieve the k-th element of an array
ary, you use the traditional syntax
ary[k].2
In order for the evaluation of this expression to succeed
(i.e., without an ArrayIndexOutOfBoundsException being thrown),
it must be that 0 ≤ k < ary.length.
To retrieve the k-th element of an ArrayList aryList, you use
the get() observer method, like this: aryList.get(k).
In order for the evaluation of this expression to succeed
(i.e., without an IndexOutOfBoundsException being thrown),
it must be that 0 ≤ k < aryList.size().
- Element Replacement:
Replacing a value in an array element is achieved by using an assignment
statement such as ary[k] = E (where E is an expression
of the appropriate data type and k is within the index range
of ary). To perform a similar feat with respect to ArrayList
aryList, you would use the set() mutator method,
like this: aryList.set(k,E). Of course, for this to work
requires 0 ≤ k < aryList.size().
- Adding/Inserting an Element:
In an array, this is not possible, per se.
In an ArrayList aryList, the method call
aryList.add(k,E) (where E is an expression of
appropriate type) places the specified element E at position
k, shifting the elements that had been at positions
[k..aryList.size()) up by one position. Of course, the
size of aryList increases by one. As you would expect,
this method call works only if k satisfies
0≤k≤aryList.size().
There is a one-argument version of add() that inserts a
new element at the end of an ArrayList. Thus, the call
aryList.add(E) is equivalent to
aryList.add(aryList.size(), E).
- Removing an Element:
In an array, this is not possible, per se.
In an ArrayList aryList, the method call
aryList.remove(k) removes the element at position k,
shifting the elements that had been at positions in the range
(k..aryList.size()) down by one position.
Of course, the size of aryList decreases by one.
As you would expect, this method call works only if k
satisfies 0 ≤ k < aryList.size().
Summary of Fundamental Operations on ArrayLists
Method Call | Effect |
size() |
Returns the number of occupying elements |
get(k) |
Returns (reference to) the element at position k |
set(k,E) |
Replaces the item at position k by E. |
add(k,E) |
Inserts E at position k, shifting elements numbered k and
higher upward
|
add(E) |
Inserts E at position size() |
remove(k) |
Removes the element at position k, shifting elements numbered k+1
and higher downward
|
Footnotes
[1] The default value for all reference (i.e., non-primitive) types is
null. For primitive numeric types (including int and
double), the default value is zero. For boolean, it is
false. For char, it is the character represented by
the number zero, which as a literal in Java is written '\0'
and is usually referred to as the null character.
[2] The array abstraction has been included in almost every widely used
programming language, going back to FORTRAN in the late 1950's.
With some minor variations, the same syntax has been used, too.
In Java, that syntax seems out of place, but the designers of Java
adopted it, probably to appeal to experienced programmers who were
familiar with it.