Using the ArrayList Class

Overview

Some people love to collect things. My wife collects lots of things: Salt and pepper shakers, nutcrackers, bears, shot glasses, and tin signs to name but a few.

If I were writing a program to keep track of one of her collections, an array would be a poor choice for storing the data. That's because on any given day, she may come home with a new item she found at an estate sale or an auction. So if she had 87 tin signs before, and I had created an array big enough to hold all 87 signs, I'd have to change the array declaration to hold 88 signs.

Java's collection classes are designed to simplify the programming for applications that have to keep track of groups of objects. These classes are very powerful and surprisingly easy to use-at least the basics, anyway. The more advanced features of collection classes take some serious programming to get right, but for most applications, a few simple methods are all you need to use collection classes.

Unfortunately, Java's collection classes are organized according to a pretty complicated inheritance hierarchy that can be very confusing for beginners. Most of the Java books I have on my shelf start by explaining this inheritance scheme and showing how each of the various collection classes fits into this scheme, and why.

I'm not going to do that-I think it's very confusing for a newcomer to collections to have to wade through a class hierarchy that doesn't make sense until you know some of the details of how the basic classes work. So (instead), I just show you how to use two of the best of these classes. In this chapter, you find out how to use the ArrayList class. Then, in the next chapter, you find out how to use its first cousin, the LinkedList. Once you know how to use these two classes, you shouldn't have any trouble learning how to use the other collection classes from the API documentation.

  TECHNICAL STAUFF 

Java 1.5 introduced a major new language feature called generics that is aimed specifically at making collections easier to work with. Because generics are an integral part of how collections work in Java 1.5 and Java 1.6, I incorporate the generics feature into this chapter from the very start. I point out the differences for using ArrayList without generics along the way, just in case you're using an older version of Java or are working with programs that were written before Java 1.5 became available. (For a complete explanation of how the generics feature works, you can refer to Book IV, Chapter 5.)

The ArrayList Class

An array list is the most basic type of Java collection. You can think of an array list as an array on steroids. It's similar to an array, but avoids many of the most common problems of working with arrays. Specifically:

The ArrayList class has several constructors and a ton of methods. For your reference, Table 3-1 lists the constructors and methods of the ArrayList class.

Table 3-1: The ArrayList Class

Open table as spreadsheet

Constructor

Explanation

ArrayList()

Creates an array list with an initial capacity of ten elements.

ArrayList(intcapacity)

Creates an array list with the specified initial capacity.

ArrayList(Collection c)

Creates an array list and copies all the elements from the specified collection into the new array list.

Open table as spreadsheet

Method

Explanation

add(Objectelement)

Adds the specified object to the array list. If you specified a type when you created the array list, the object must be of the correct type.

add(intindex, Object element)

Adds the specified object to the array list at the specified index position. If you specified a type when you created the array list, the object must be of the correct type.

addAll(Collectionc)

Adds all the elements of the specified collection to this array list.

addAll(intindex, Collection c)

Adds all the elements of the specified collection to this array list at the specified index position.

clear()

Deletes all elements from the array list.

clone()

Returns a shallow copy of the array list. The elements contained in the copy are the same object instances as the elements in the original.

contains(Object elem)

Returns a boolean that indicates whether the specified object is in the array list.

containsAll (Collection c)

Returns a boolean that indicates whether this array list contains all the objects that are in the specified collection.

ensureCapacity(int minCapacity)

Increases the array list's capacity to the specified value. (If the capacity is already greater than the specified value, this method does nothing.)

get(int index)

Returns the object at the specified position in the list.

indexOf(Object elem)

Returns the index position of the first occurrence of the specified object in the array list. If the object isn't in the list, returns −1.

isEmpty()

Returns a boolean value that indicates whether the array list is empty.

iterator()

Returns an iterator for the array list.

lastIndexOf(Object elem)

Returns the index position of the last occurrence of the specified object in the array list. If the object isn't in the list, returns −1

.remove(int index)

Removes the object at the specified index. Returns the element that was removed.

remove(Object elem)

Removes an object from the list. Note that more than one element refers to the object; this method removes only one of them. Returns a boolean that indicates whether the object was in the list.

remove(int fromIndex, int toIndex)

Removes all objects whose index values are between the values specified. Note that the elements at the fromIndex and toIndex positions are not themselves removed.

removeAll(Collection c)

Removes all the objects in the specified collection from this array list.

retainAll(Collection c)

Removes all the objects that are not in the specified collection from this array list.

set(int index, Object elem)

Sets the specified element to the specified object. The element that was previously at that position is returned as the method's return value.

size()

Returns the number of elements in the list.

toArray()

Returns the elements of the array list as an array of objects (Object[]).

toArray(type[] array)

Returns the elements of the array list as an array whose type is the same as the array passed via the parameter.

The rest of this chapter shows you how to use these constructors and methods to work with ArrayList objects.

Creating an ArrayList Object

To create an array list, you first declare an ArrayList variable, and then call the ArrayList constructor to instantiate an array list object and assign it to the variable. You can do this on separate lines:

ArrayList signs; signs = new ArrayList();

or, you can do it on a single line:

ArrayList signs = new ArrayList();

Here are a few things to note about creating array lists:

Adding Elements

After you create an array list, you can use the add method to add objects to the array list. For example, here's code that adds strings to an array list:

signs.add("Drink Pepsi"); signs.add("No minors allowed"); signs.add("Say Pepsi, Please"); signs.add("7-Up: You Like It, It Likes You"); signs.add("Dr. Pepper 10, 2, 4");

If you specified a type when you created the array list, the objects you add via the add method must be of the correct type.

You can insert an object at a specific position in the list by listing the position in the add method. For example, consider these statements:

ArrayList nums = new ArrayList(); nums.add("One"); nums.add("Two"); nums.add("Three"); nums.add("Four"); nums.add(2, "Two and a half");

After these statements execute, the nums array list contains the following strings:

One Two Two and a half Three Four

Here are some important points to keep in mind when you add elements to array lists:

Accessing Elements

To access a specific element in an array list, you can use the get method. It specifies the index value of the element you want to retrieve. For example, here's a for loop that prints all the strings in an array list:

for (int i = 0; i < nums.size(); i++) System.out.println(nums.get(i));

Here the size method is used to set the limit of the for loop's index variable.

The easiest way to access all the elements in an array list is by using an enhanced for statement. It lets you retrieve the elements without bothering with indexes or the get method. For example:

for (String s : nums) System.out.println(s);

Here, each String element in the nums array list is printed to the console.

If you need to know the index number of a particular object in an array list and you have a reference to the object, you can use the indexOf method. For example, here's an enhanced for loop that prints the index number of each string along with the string:

for (String s : nums) { int i = nums.indexOf(s); System.out.println("Item " + i + ": " + s); }

Depending on the contents of the array list, the output from this loop looks something like this:

Item 0: One Item 1: Two Item 2: Three Item 3: Four

Printing an ArrayList

The toString method of the ArrayList class (as well as other collection classes) is designed to make it easy to quickly print out the contents of the list. It returns the contents of the array list enclosed in a set of brackets, with each element value separated by commas. The toString method of each element is called to obtain the element value.

For example, consider these statements:

ArrayList nums = new ArrayList(); nums.add("One"); nums.add("Two"); nums.add("Three"); nums.add("Four"); System.out.println(nums);

When you run these statements, the following is displayed on the console:

[One, Two, Three, Four]

Although this output isn't very useful for actual applications, it's convenient for testing purposes or for debugging problems in programs that use array lists.

Using an Iterator

Another way to access all the elements in an array list (or any other collection type) is to use an iterator. An iterator is a special type of object whose sole purpose in life is to let you step through the elements of a collection.

  Tip 

The enhanced for statement introduced with Java 1.5 is designed to simplify programs that use iterators. As a result, if you're using Java 1.5 or later, you can use the enhanced for statement instead of iterators. Still, you'll probably encounter existing programs that use iterators, so you need to know how they work.

An iterator object implements the Iterator interface, which is defined as part of the java.util package. As a result, to use an iterator, you must import either java.util.Iterator or java.util.*. The Iterator interface defines just three methods, as listed in Table 3-2. These methods are all you need to access each element of a collection. (Actually, you only need the hasNext and next methods. The remove method is gravy.)

Table 3-2: The Iterator Interface

Open table as spreadsheet

Method

Explanation

hasNext()

Returns true if the collection has at least one element that hasn't yet been retrieved.

next()

Returns the next element in the collection.

remove()

Removes the most recently retrieved element.

  DESIGN PATTERN 

The Iterator pattern

Java's iterators follow a commonly known design pattern called the Iterator pattern. The Iterator pattern is useful whenever you need to provide sequential access to a collection of objects. The Iterator pattern relies on interfaces so the code that's using the iterator does-n't have to know what actual class is being iterated. As long as the class implements the iterator interface, it can be iterated.

The Iterator interface itself defines the methods used for sequential access. The common pattern is for this interface to provide at least two methods:

  • hasNext: Returns a boolean value that indicates whether another item is available.
  • next: Returns the next item.

Java also defines a third method for its Iterator interface: remove, which removes the most recently retrieved object.

In addition to the Iterator interface, the collection class itself needs a way to get an iterator object. It does so via the iterator method, which simply returns an iterator object for the collection. The iterator method is defined by the Iterable interface. Thus, any object that implements Iterable has an iterator method that provides an iterator for the object.

To use an iterator, you first call the array list's iterator method to get the iterator. Then you use the iterator's hasNext and next methods to retrieve each item in the collection. The normal way to do that is with a while loop; here's an example:

ArrayList nums = new ArrayList(); nums.add("One"); nums.add("Two"); nums.add("Three"); nums.add("Four"); String s; Iterator e = nums.iterator(); while (e.hasNext()) { s = (String)e.next(); System.out.println(s); }

Here the first five statements create an array list and add four strings to it. Next, the iterator method is called to get an iterator for the nums array list. The hasNext method is called in the while statement, and the next method is called to get the element to be printed.

  TECHNICAL STAUFF 

Note that the object returned by the next method must be cast to a String. That's because the Iterator interface has no knowledge of the type of objects stored in the collection. As a result, it simply returns an Object. You must then cast this object to the correct type before you can use it.

Updating Elements

You can use the set method to replace an existing object with another object. Consider this example:

ArrayList nums = new ArrayList(); nums.clear(); nums.add("One"); nums.add("Two"); nums.add("Three"); System.out.println(nums); nums.set(0, "Uno"); nums.set(1, "Dos"); nums.set(2, "Tres"); System.out.println(nums);

Here an array list is created with three strings, and the contents of the array list are printed to the console. Then each of the three strings is replaced by another string, and the contents print to the console again. When you run this code, the following is what you see printed on the console:

[One, Two, Three] [Uno, Dos, Tres]

  Tip 

Because array lists contain references to objects, not the objects themselves, any changes you make to an object in an array list are automatically reflected in the list. As a result, you often don't have to use the set method.

For example:

ArrayList emps = new ArrayList(); // add employees to array list emps.add(new Employee("Addams", "Gomez")); emps.add(new Employee("Taylor", "Andy")); emps.add(new Employee("Kirk", "James")); // print array list System.out.println(emps); // change one of the employee's names Employee e = emps.get(1); e.changeName("Petrie", "Robert"); // print the array list again System.out.println(emps);

It uses the Employee class whose constructor accepts an employee's last name and first name to create a new employee object, as well as a changeName method that also accepts a last name and a first name. In addition, the Employee class overrides the toString method to return the employee's first name and last name.

The main method begins by creating an ArrayList object and adding three employees. Then it prints out the contents of the array list. Next, it retrieves the employee with index number 1 and changes that employee's name. Finally, it prints the contents of the array list again.

Here's what this code produces on the console:

[Gomez Addams, Andy Taylor, James Kirk] [Gomez Addams, Robert Petrie, James Kirk]

Notice that the second employee's name was changed, even though the program doesn't use the set method to replace the changed Employee object in the collection. That's because the array list merely stores references to the Employee objects.

Deleting Elements

The ArrayList class provides several methods that let you remove elements from the collection. To remove all the elements, use the clear method, like this:

emps.clear();

To remove a specific element, use the remove method. It lets you remove an element based on the index number, like this:

emps.remove(0);

Here the first element in the array list is removed.

Alternatively, you can pass the actual object you want removed. This is useful if you don't know the index of the object you want to remove, but you happen to have a reference to the actual object as in this example:

ArrayList emps = new ArrayList(); // create employee objects Employee emp1 = new Employee("Addams", "Gomez"); Employee emp2 = new Employee("Taylor", "Andy"); Employee emp3 = new Employee("Kirk", "James"); // add employee objects to array list emps.add(emp1); emps.add(emp2); emps.add(emp3); // print the array list System.out.println(emps); // remove one of the employees emps.remove(emp2); // print the array list again System.out.println(emps);

Here's what this code produces on the console:

[Gomez Addams, Andy Taylor, James Kirk] [Gomez Addams, James Kirk]

As you can see, Andy Taylor was removed from the list without knowing his index position.

Here are a few important details to keep in mind:

Категории