«^»
3.2. The interface List and the classes ArrayList and LinkedList

A list is an ordered collection of elements, where each element contains a pointer to a value. You could visualize an object that is a list as:

A list of the methods that can be applied to an object that is a list is given at javaapi:java/util/List.html.

To begin with, we will just consider the following methods of the List interface:

We will now look at an example that shows how these methods can be used.

In the example, we will use the class Person that was produced in ITS Guide 58: Getting started with Java. Suppose we have three people:

Person tTom   = new Person("Tom%1.6%1981-12-25");
Person tDick  = new Person("Dick%1.7%1980-3-18");
Person tHarry = new Person("Harry%1.8%1979-8-4");
Suppose we want to create a list containing these three people. List is an interface, and (as was mentioned earlier) the Collections API provides two classes that implement this interface: they are ArrayList and LinkedList. So a list can be created using either:
List tList = new ArrayList();
or:
List tList = new LinkedList();
Both of these statements create an empty list.

Suppose we use an ArrayList. We can visualize the ArrayList's empty list as follows:

Having created the empty list, the statements:

int tSize = tList.size();
boolean tIsEmpty = tList.isEmpty();
assign 0 to the variable tSize and the value true to tIsEmpty.

Suppose tTom points to a Person object. We can add the tTom object to the list using:

tList.add(tTom);
The result can be visualized as:

where only the first field of the Person object has been shown in detail.

The designers of the Collections API have chosen to share the objects of a collection with clients of the collection. This means that the add method does not make its own copy of the object pointed to by tTom: it just establishes a new element of the list that points to the object that tTom is pointing to. So, the value of any element of the list that points to the tTom object will be affected if we later choose to change the value of the object pointed to by tTom.

If we now do:

tList.add(tHarry);    // TH
the list will contain two elements, the first one describing Tom, the second one describing Harry. The comment after the call of add, i.e., // TH, gives a cryptic indication of the state of the list after the method call has been executed.

So we now have the following situation:

The add method has a parameter that is of the class Object. This means that the method can be used with an object of any class. It also means that the argument of the call does not have to be of the same class each time we call the method, and so we could build lists where the elements of the list do not have the same class.

The get method can be used to obtain the value of any element of the list. This method has one parameter: it indicates the position of the element in the list. The numbering of the elements starts from 0 (rather than from 1). So to get a pointer to the object at the first element of the list use:

Person tFirstPerson = (Person)tList.get(0);
Because a List can be used to store objects of any class, the result type of get is Object. So tList.get(0) returns a value of class Object and we have to cast this in order to treat the object as a Person object. If you cast to the wrong type, then (at execution time) the program will crash with a ClassCastException.

The above statement results in a situation that can be visualized as:

Note again that, because the Collections API adopts the share approach, tFirstPerson points to the same object as that of one of the elements of the list.

If we also execute the statements:

System.out.println(tFirstPerson);
System.out.println((Person)tList.get(1));
System.out.println(tList.size());
the following would be output:
Tom%1.6%1981-12-25
Harry%1.8%1979-08-04
2

When add is used with one argument as in the calls given earlier, the new element is added at the end of the list. Instead, we can use add with an additional argument that indicates a position:

tList.add(1, tDick);     // TDH
This means that tDick is to be inserted at position 1 and the element previously at position 1 is now at position 2.

Here are some other examples of calls of methods from the List interface:

tList.add(3, tHarry);    // TDHH  
tList.add(0, tDick);     // DTDHH  
tList.remove(tHarry);    // DTDH  
tList.remove(1);         // DDH  
tList.set(0, tTom);      // TDH  
where the comments give a cryptic description of the state of the list after each statement has been executed.