ArrayLists and Iterators
Site: | Saylor Academy |
Course: | CS101: Introduction to Computer Science I |
Book: | ArrayLists and Iterators |
Printed by: | Guest user |
Date: | Wednesday, October 30, 2024, 3:20 PM |
Description
Read this chapter about lists and the useful methods that are available for adding and inserting elements into a list.
Table of contents
- 1. ArrayLists and Iterators
- 2. Fixed-length Array
- 3. Old Information is Lost
- 4. ArrayList class
- 5. Example Program
- 6. Example Program Continued
- 7. Constructors for ArrayList Objects
- 8. Capacity and Size
- 9. List Interface
- 10. Summary List Interface
- 11. Adding Elements to an ArrayList
- 12. Setting ArrayList Elements
- 13. Adding at a Specific Index
- 14. Removing an Element
- 15. isEmpty()
- 16. Searching for an Element
- 17. Iterator
- 18. Enhanced for Loop
- 19. Wrapper Classes
- 20. Autoboxing
- 21. Boxing and Unboxing
- 22. Phone Book Application
- 23. Entry Methods
- 24. Testing for Equality
- 25. Must Override the Right Method
- 26. Test Program
- 27. Test Program
- 28. Details
- 29. Playful Program
- 30. Improved Program
- 31. null as an Element
- 32. End of Chapter
1. ArrayLists and Iterators
Programs frequently keep data in lists. Often, arrays are used for this. Arrays are a fundamental feature of most programming languages. But because lists are so useful, Java includes the ArrayList
class, which works much like an
array with extra methods and features.
Like an array, an ArrayList
contains elements that are accessed using an integer index. However, unlike an array, the size of an ArrayList
is not fixed. An ArrayList
expands as needed
as items are added to it.
The class ArrayList
is one of the standard classes that students are expected to know for the Advanced Placement test given in the United States. Every AP test for the past several years has included a programming problem involving
this class.
Several of the features described in this chapter are new to Java 5.0. Versions of Java older than that will not work.
Chapter Topics:
- Review of fixed-length arrays
- The
ArrayList
class ArrayList
constructors- The
List
interface - capacity and size
- Methods of
ArrayList
add()
,clear()
get()
,indexOf()
isEmpty()
,remove()
,size()
- Iterators
- Autoboxing
Question 1:
(Review: ) Examine the following:
String[] list = new String[3];
What is the length of the array referenced by list
?
Source: Bradley Kjell, http://programmedlessons.org/Java9/chap85/ch85_01.html
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 License.
2. Fixed-length Array
Answer:
The array object has three cells.
Fixed-length Array
Once an array object has been constructed, the number of cells does not change. You must construct an array with a length that will accommodate all the data you expect. Unfortunately, sometimes this length is hard to determine. A program might need different sizes each time it is run. It would be nice if there were a type of array that allowed you to keep adding data regardless of its original length.
A cell of an array is a place where data may be stored. An array may contain many cells. The cells are numbered from 0 up to one less than the length of the array.
An element is the data that has been placed in a cell. (Sometimes an element is called an item, a value, or an entry.)
Question 2:
An array has been completely filled with information:
String[] list = new String[3];
list[0] = "ant" ;
list[1] = "bat" ;
list[2] = "cat" ;
After running for a while, the program needs to add information to the array. Will the following statement make the array larger?
list = new String[5];
3. Old Information is Lost
Answer:
No. The statement creates a completely new array object (with 5 cells). The old array object and the information it contains is now garbage unless some other reference variable points to it.
Old Information is Lost
In the example, the reference variable list
is set to the newly constructed object. The diagram shows what happens. The diagonal slashes represent null
, the value that means "no object".
The information in the old array is not transferred to the new array. To keep the old information, the program must keep a reference to the old array and copy the old information to the new array. This is not too hard to do, but it is a nuisance.
Question 3:
What happens if information is added to a cell that does not exist?
String[] list = new String[3]; list[0] = "ant" ; list[1] = "bat" ; list[2] = "cat" ; list[3] = "dog" ;
4. ArrayList class
Answer:
An ArrayIndexOutOfBounds
exception is thrown and (usually) the program halts.
ArrayList
class
The ArrayList
class builds
upon the capabilities of arrays. An ArrayList
object contains an array of object references plus many methods for managing that array.
The biggest convenience of a ArrayList
is that you can keep adding elements to it no matter what size it was originally. The size of the ArrayList
automatically increases and no information
will be lost.
However, this convenience comes at a price:
- The elements of an
ArrayList
must be object references, not primitive data likeint
ordouble
. ArrayList
operations are slightly slower than array operations.
In the picture, "X" shows that a cell is empty. The ArrayList
in the picture is completely empty. The "X" is conceptual; the actual implementation of ArrayList
uses an unspecified means to keep track
of empty cells.
Note: "X" is not the value null
. If null
is placed in a cell, the cell is regarded as containing data.
Question 4:
(Thought Question: ) Say that you want a list of
int
values. But anArrayList
can contain only object references. How can you use anArrayList
to store yourint
s? (Click for a hint.)
5. Example Program
Answer:
You can encapsulate your integers in Integer
objects and store them in an ArrayList
.
Example Program
import java.util.* ; public class ArrayListEg { public static void main ( String[] args) { // Create an ArrayList that holds references to String ArrayList<String> names = new ArrayList<String>(); // Add three String references names.add("Amy"); names.add("Bob"); names.add("Cindy"); // Access and print out the three String Objects System.out.println("element 0: " + names.get(0) ); System.out.println("element 1: " + names.get(1) ); System.out.println("element 2: " + names.get(2) ); } } |
The example program creates an ArrayList
that holds String
references and then adds references to three String
s. The statement
ArrayList<String> names = new ArrayList<String>();
creates an ArrayList
of String
references. The phrase <String>
can be read as "of String references". Note that there are "angle brackets" on each side of <String>
.
The phrase ArrayList<String>
describes both the type of the object that is constructed (an ArrayList
) and the type of data it will hold (references to String
).
ArrayList
is a generic type, which means that its constructor specifies both the type of object to construct and the type that the new object will hold. The type the object will hold is placed inside angle brackets
like this: <DataType>
. Now, when the ArrayList
object is constructed, it will hold data of type "reference to DataType".
A program must import the java.util
package to use ArrayList
.
By default, an ArrayList
starts out with 10 empty cells.
Question 5:
Examine the following:
ArrayList<Integer> values = new ArrayList<Integer>();
What type of data will
values
hold?
6. Example Program Continued
Answer:
The list will hold references to Integer
objects.
Example Program Continued
import java.util.* ; public class ArrayListEg { public static void main ( String[] args) { // Create an ArrayList that holds references to String ArrayList<String> names = new ArrayList<String>(); // Add three String references names.add("Amy"); names.add("Bob"); names.add("Cindy"); // Access and print out the three String Objects System.out.println("element 0: " + names.get(0) ); System.out.println("element 1: " + names.get(1) ); System.out.println("element 2: " + names.get(2) ); } } |
In the program, the ArrayList
holds references of type String
or a subclass of String
.
In the picture, three elements have been added. The references are added in order starting with cell 0 of the array.
Then the program accesses the references using the get()
method and prints out the String
s. The output of the program is:
element 0: Amy
element 1: Bob
element 2: Cindy
The names.get( int index )
method returns the reference in the cell at index
. If the cell is empty, an IndexOutOfBoundsException
will be thrown and the program will halt (unless
there is code to handle the exception.)
Question 6:
Suppose that the following follows the first three
add
statements:names.add("Daniel");
Where will the reference to "Daniel" be added?
7. Constructors for ArrayList Objects
Answer:
A reference to "Daniel" will be added to cell 3 of the array (right after the reference to "Cindy").
Constructors for ArrayList
Objects
ArrayList
ObjectsTo declare a reference variable for an ArrayList
do this:
ArrayList<E> myArray;
myArray
is a reference to a future ArrayList object. The future ArrayList
object will contain an array of references to objects of type E
or to a descendant class of E
.
Construct the ArrayList
later on in the code:
myArray = new ArrayList<E>();
The array has an initial capacity of 10 cells, although the capacity will increase as needed as references are added to the list. Cells will contain references to objects of type E
(or a descendant class). This may not be very efficient. If you have an idea of the capacity needed, start the ArrayList
with that capacity.
To both declare a reference variable and construct an ArrayList
, do this:
ArrayList<E> myArray = new ArrayList<E>();
To declare a variable and to construct a ArrayList
with a specific initial capacity do this:
ArrayList<E> myArray = new ArrayList<E>( int initialCapacity );
The initial capacity is the number of cells that the ArrayList
starts with. It can expand beyond this capacity if you add more elements. Expanding the capacity of an ArrayList
is slow. To avoid this, estimate how many elements are needed and construct an ArrayList
of that many plus some extra.
Question 7:
Say that you are writing a program to keep track of the students in a course. There are usually about 25 students, but a few students may add the class, and a few students may drop the class. Data for a student is kept in a
Student
object. Declare and construct anArrayList
suitable for this situation.
8. Capacity and Size
Answer:
ArrayList<Student> students = new ArrayList<Student>( 30 );
A rough estimate for the capacity is good enough. It is better to overestimate it than to underestimate it. A few unused cells do not hurt.
Capacity and Size
An ArrayList
object has a capacity and a size.
- The capacity is the total number of cells.
- The size is the number of cells that have data in them.
- Cells 0 up through size-1 have data in them.
- Data is added in order. Before cell N gets data, cells 0, 1, 2, ... N-1 must hold data.
The size increases by one each time an element is added. However, the capacity remains unchanged until the ArrayList
is full. When an element is added to a full list, the Java runtime system will greatly increase the capacity of the list so that many more elements can be added.
To find out the current size of an ArrayList
use its size()
method.
Question 8:
What is the capacity of the
ArrayList
in the picture?What is its size?
9. List Interface
Answer:
What is the capacity of the ArrayList
in the picture?
10
What is its size?
3
List<E>
Interface
List<E>
Interface
Lists of things are common in the real world and in programming. People make lists of things they need to buy and lists of things they need to do. A text editor keeps a list of pages. A test consists of a list of questions.
ArrayList
implements the List<E>
interface. The List<E>
interface captures the idea of a list without saying how the idea is implemented. ArrayList
is just one implementation of the idea.
Recall that an interface consists of constants and method declarations. A class that implements an interface must implement each of the methods listed in the interface. There are no constants in List<E>
, but there are many methods.
A list is an ordered collection of elements. Duplicate elements are allowed in an ArrayList
(and in most other implementations of List<E>
). Elements in a list can be accessed by their index, as with an array. There are methods to add elements, get elements, remove elements, and search for elements (and many other methods).
Question 9:
What is the index of the first cell of a list?
10. Summary List Interface
Answer:
0, just as with an array.
Summary List<E>
Interface
List<E>
Interface
Here is a summary of the List<E>
Interface. For the full interface see the Java documentation.
Method | What it Does |
---|---|
boolean add(E elt) |
Appends element elt to the end of the list. |
void add(int index, E elt) |
Inserts element elt at the specified index. |
E remove(int index) |
Removes the element at the specified index. |
void clear() |
Remove all elements, so the list is now empty. |
int indexOf(Object elt) |
Searches for the first occurrence of elt, testing for equality using the equals(Object) method. |
boolean isEmpty() |
tests if the list is empty |
E set(int index, E elt) |
Replaces the element at index with the specified element elt. |
. . . many more . . . | . . . |
The E
in these descriptions means reference to object of type E
or of its subclasses. Of course, the List
must have been constructed to hold references to that type.
Question 10:
Here is a declaration and construction of a
ArrayList
:ArrayList<String> data = new ArrayList<String>(10);
Which of the following statements will work?
data.add( "Irene Adler" );
data.add( new String("Laura Lyons") );
data.add( 221 );
data.add( new Integer( 221 ) );
11. Adding Elements to an ArrayList
Answer:
ArrayList<String> data = new ArrayList<String>(10);
Which of the following statements will work?
data.add( "Irene Adler" ); // OK
data.add( new String("Laura Lyons") ); // OK
data.add( 221 ); // wrong type of argument
data.add( new Integer( 221 ) ); // wrong type of argument
Adding Elements to an ArrayList
ArrayList
ArrayList
implements the List<E>
Interface.
To add an element to the end of an ArrayList
use:
// Add a reference to an object elt to the end of the ArrayList,
// increasing size by one. The capacity will increase if needed.
// Always returns true.
boolean add( E elt ) ;
To access the element at a particular index use:
E get( int index )
This method returns a reference to an object in the list, which is of type E
. Here is our example program, where type E
is String
.
import java.util.* ; public class ArrayListEgTwo { public static void main ( String[] args) { // Create an ArrayList that holds references to String ArrayList<String> names = new ArrayList<String>(); // Capacity starts at 10, but size starts at 0 System.out.println("initial size: " + names.size() ); // Add three String references names.add("Amy"); names.add("Bob"); names.add("Cindy"); System.out.println("new size: " + names.size() ); // Access and print out the Objects for ( int j=0; j<names.size(); j++ ) System.out.println("element " + j + ": " + names.get(j) ); } } |
ArrayList
of references to String
objects. The for
statement uses size()
for the upper bound of the loop. This works
because there are never any empty cells between the elements of the list.Question 11:
12. Setting ArrayList Elements
Answer:
size: 0
new size: 3
element 0: Amy
element 1: Bob
element 2: Cindy
Setting ArrayList
Elements
ArrayList
Elements
The add(E elt)
method adds to the end of an ArrayList
. But sometimes you want to change the element at a particular index.
set( int index, E elt )
The element previously at index
is replaced with the reference elt
. The index
should be in the range 0 to size-1.
An IndexOutOfBoundsException
is thrown if the index is out of bounds. (For now, this means that the program will halt.)
The index must be in the range 0 to size-1, which are the indexes of cells already occupied. This method can't "skip over" empty cells when it adds an element. It can't be used to make a list that has gaps in it.
The program first builds a list of three elements, then replaces the element at index zero.
|
Question 12:
13. Adding at a Specific Index
Answer:
element 0: Amy
element 1: Bob
element 2: Cindy
element 0: Zoe
element 1: Bob
element 2: Cindy
Adding at a Specific Index
You can insert an element at a specific index from 0
to size()
. The newly added element is now located at the specified index, and the indexes of all elements above that element is increased by one. If you
add an element at index size()
, the element is appended to the end of the list.
void add(int index, E elt) // Inserts the element atindex
. Each element with
// an index greater thanindex
is shifted upward
// and now has an index one greater than its previous value.
The method throws an IndexOutOfBoundsException
if the index is out of bounds, either negative or greater than size()
. This prevents you from creating a list with gaps between elements. The following program
uses this method:
import java.util.* ; public class ArrayListEgFour { public static void main ( String[] args) { ArrayList<String> names = new ArrayList<String>(); names.add( "Amy" ); names.add( "Bob" ); names.add( "Chris" ); // Print original arrangement System.out.println("Before adding at index 1:"); for ( int j=0; j < names.size(); j++ ) System.out.println( j + ": " + names.get(j) ); // Insert an element names.add( 1, "Valerie"); // Print new arrangement System.out.println("\nAfter adding at index 1:"); for ( int j=0; j < names.size(); j++ ) System.out.println( j + ": " + names.get(j) ); } } |
The program prints out:
Before adding at index 1:
0: Amy
1: Bob
2: Chris
After adding at index 1:
0: Amy
1: Valerie
2: Bob
3: Chris
Question 13:
Would the following statement work in the above program?
names.add(5, "Gertrude");
14. Removing an Element
Answer:
No. You are not allowed to create gaps between elements. Adding an element at index 5 in the above program would generate a runtime error.
Removing an Element
To remove an element from a list use the remove()
method. This method removes an element without leaving a hole. The object references above the removed element are moved down to fill the gap.
E remove(int index) // Delete the element atindex
. Each element with an index
// greater thanindex
is shifted downward to have an index
// one smaller than its previous value.
// Returns a reference to the removed element.
// Throws anIndexOutOfBoundsException
if the index is out
// of range.
The object reference at location index
is removed from the list. Elements at locations index+1, index+2, ... , size()-1
are each moved down one to fill in the gap. This is like pulling out a book from the
middle of a stack of books.
The object reference that was removed from the list is the return value of the method. This value can be assigned to a reference variable. As long as there is a reference to the object, the object is not lost. If the only reference to the object was the one in the list, and that reference is not assigned to a variable, then the object will be garbage collected.
Question 14:
Examine the following program. What will it print?
import java.util.* ;
public class DeleteEg
{
public static void main ( String[] args)
{
ArrayList<String> names = new ArrayList<String>();
names.add( "Amy" );
names.add( "Bob" );
names.add( "Chris" );
names.add( "Deb" );
names.remove(2);
for ( int j=0; j < names.size(); j++ )
System.out.println( j + ": " + names.elementAt(j) );
}
}
15. isEmpty()
Answer:
0: Amy
1: Bob
2: Deb
isEmpty()
isEmpty()
To check if an ArrayList
has elements use
boolean isEmpty()
which returns true
if the cells of the ArrayList
are all empty.
Warning:The value null
in a cell counts as data. An empty cell is not the same as a cell that contains null
.
To remove all elements from a list, use
void clear()
Question 15:
(Puzzle: ) What will the following program print?
import java.util.* ;
public class NullPuzzle
{
public static void main ( String[] args)
{
ArrayList<String> nobby = new ArrayList<String>();
System.out.println( "Case A:" + nobby.isEmpty() );
nobby.add( null );
System.out.println( "Case B:" + nobby.isEmpty() );
nobby.remove( 0 );
System.out.println( "Case C:" + nobby.isEmpty() );
nobby.add( "" );
System.out.println( "Case D:" + nobby.isEmpty() );
nobby.clear( );
System.out.println( "Case E:" + nobby.isEmpty() );
}
}
16. Searching for an Element
Answer:
Case A:true
Case B:false
Case C:true
Case D:false
Case E:true
Case A: the list starts out empty, so isEmpty()
returns true.
Case B: the value null
has been added to the list, and is now held at index zero. isEmpty()
returns false.
Case C: the value at index zero has been removed from the list. isEmpty()
returns true.
Case D: a reference to a string has been added to the list at index zero. The string happens to be the empty string, but it is a legitimate object and the cell at index zero holds a reference to it. isEmpty()
returns false.
Case E: clear()
has made the list empty. isEmpty()
returns true.
Searching for an Element
Searching for an Element
Linear search starts at the first element and examines elements one by one until the target element is found. You could write linear search for an ArrayList
but there is a method that does this for you:
int indexOf(Object element) // Search for the first occurrence of //element
, testing for equality // using the equals(Object) method ofelement
.
The method returns the index of the first occurrence of element
or -1
if element
is not found.
Question 16:
Examine the following program. What will it print?
import java.util.* ;
public class SearchEg
{
public static void main ( String[] args)
{
ArrayList<String> names = new ArrayList<String>();
names.add( "Amy" );
names.add( "Bob" );
names.add( "Chris" );
names.add( "Deb" );
names.add( "Elaine" );
names.add( "Joe" );
System.out.println( "First Search: " + names.indexOf( "Elaine" ) );
System.out.println( "Secnd Search: " + names.indexOf( "Zoe" ) );
}
}
17. Iterator
Answer:
First Search: 4
Secnd Search: -1
Iterator
Iterator
Often you wish to access the elements of an ArrayList
one by one, in order. You could write a counting loop (as has been done so far in this chapter). Or, you could use an Iterator
object. To get an Iterator
object,
use this method of ArrayList
:
Iterator<E> iterator() // Returns an iterator
ArrayList
implements the Iterable
interface. iterator()
is the only method in this interface.
An iterator object is used to visit the elements of a list one by one. It visits only the cells that have data (so you don't need to worry about going past the end of data). This is more convenient than writing a loop. An iterator implements
the
Iterator<E>
interface, which has the following methods:
boolean hasNext() // Returns true if not all elements have been visited
E next() // Returns the next element of the list,
// a reference to type E
void remove() // Remove from the list the element just returned by next()
Here is a program that prints out every element in the ArrayList
:
import java.util.* ; public class IteratorExample { public static void main ( String[] args) { // Create and populate the list ArrayList<String> names = new ArrayList<String>(); names.add( "Amy" ); names.add( "Bob" ); names.add( "Chris" ); names.add( "Deb" ); names.add( "Elaine" ); names.add( "Frank" ); names.add( "Gail" ); names.add( "Hal" ); // Create an iterator for the list Iterator<String> iter = names.iterator(); // Use the iterator to visit each element while ( iter.hasNext() ) System.out.println( iter.next() ); } } |
Several classes in the Java libraries implement the Iterator<E>
interface. Some of these classes are complicated, and a simple loop can't be used to access all their elements. For those classes, an iterator, which systematically
accesses each element, is very useful.
Confusion Alert: Pay attention to the TWO interfaces:
Iterable
interface -- a class that implements this can create anIterator
for itself.Iterator<E>
interface -- anIterator
implements methods to visit the elements of a list.
Question 17:
Say that a program has the following code:
ArrayList<Integer> primes = new ArrayList<Integer>();
Assume that the list has been populated with elements. Fill in the following to create an iterator for the list:
18. Enhanced for Loop
Answer:
Iterator <Integer> visitor = primes.iterator() ;
Enhanced for Loop
Enhanced for Loop
Iterable
interface, such as ArrayList
. Here is the previous program, now written using an enhanced for loop.
import java.util.* ; public class IteratorExampleTwo { public static void main ( String[] args) { ArrayList<String> names = new ArrayList<String>(); names.add( "Amy" ); names.add( "Bob" ); names.add( "Chris" ); names.add( "Deb" ); names.add( "Elaine" ); names.add( "Frank" ); names.add( "Gail" ); names.add( "Hal" ); for ( String nm : names ) System.out.println( nm ); } } |
The program does the same thing as the previous program. The enhanced for loop accesses the String
references in names
and assigns them one-by-one to nm
. With an enhanced for loop there is no danger an index will go out of bounds. (There is a colon : separating nm
and names
in the above. This might be hard to see in your browser.)
The enhanced for loop only visits those cells that are not empty, beginning with cell zero. Since an ArrayList
never has gaps between cells, all occupied cells are visited.
Question 18:
(Review: ) Can primitive types, like
int
anddouble
be added to anArrayList
?
19. Wrapper Classes
Answer:
No.
The non-empty cells of an ArrayList
must contain object references (or null
).
Wrapper Classes
Wrapper Classes
int
into an ArrayList
, put the int
inside of an Integer
object. Now the object can be put into an ArrayList
. The following program builds a list of integers and then writes them out.
import java.util.* ; public class WrapperExample { public static void main ( String[] args) { ArrayList<Integer> data = new ArrayList<Integer>(); data.add( new Integer(1) ); data.add( new Integer(3) ); data.add( new Integer(17) ); data.add( new Integer(29) ); for ( Integer val : data ) System.out.print( val + " " ); System.out.println( ); } } |
The program writes out:
1 3 17 29
The picture emphasizes that the ArrayList
contains an array of object references, as always. It shows the int
s each contained in a little box that represents the wrapper object.
Question 19:
Would this statement work in the program?
data.add( 44 );
20. Autoboxing
Answer:
You would not expect
data.add( 44 );
to work, since it seems to be adding primitive data directly into the list of object references.
Autoboxing
Autoboxing
However, the statement is correct. The Java compiler expects an object reference. So when it sees
data.add( 44 );
it must supply an object reference for add()
, and automatically does the equivalent of this:
data.add( new Integer(44) );
This feature is called autoboxing and is new with Java 5.0.
Unboxing works the other direction. The int
inside a wrapper object is automatically extracted if an expression requires an int
. The following
int sum = 24 + data.get(1) ;
extracts the int
in cell 1 of data and adds it to the primitive int
24.
Question 20:
Does the following work?
Double value = 2.5; double sum = value + 5.7;
21. Boxing and Unboxing
Answer:
Double value = 2.5;
double sum = value + 5.7;
Yes, this works. It is shorthand for
Double value = new Double( 2.5 );
double sum = value.doubleValue() + 5.7;
Boxing and Unboxing
ArrayList
of Integer
references. The arguments to add()
look like int
literals, but at runtime, the int
s
are autoboxed into Integer
objects.
import java.util.* ; public class WrapperExampleTwo { public static void main ( String[] args) { ArrayList<Integer> data = new ArrayList<Integer>(); // Autoboxing used here to create Integer objects data.add( 1 ); data.add( 3 ); data.add( 17 ); data.add( 29 ); int sum = 0; for ( Integer val : data ) sum += val; // Unboxing used here to extract the ints System.out.print( "sum = " + sum ); System.out.println( ); } } |
The for-each loop visits the Integer
objects one by one. The statement
sum += val; // Unboxing used here to extract the ints
requires a primitive int
to add to the sum. Unboxing extracts the int
from the Integer
that val
points to.
Question 21:
Do you think that the following fragment will work:
Double total, meal, tax; meal = 20.00; tax = meal*0.12; total = meal+tax; System.out.println("Total Cost: " + total );
22. Phone Book Application
Answer:
The program fragment works.
Double total, meal, tax;
meal = 20.00; // autobox the 20.0
tax = meal*0.12; // unbox meal, do the math, autobox the product
total = meal+tax; // unbox meal and tax, do the math, autobox the total
System.out.println("Total Cost: " + total ); // unbox total, convert to String, concatenate
Even though this works, it is not sensible code. There is no reason to use the Double
wrapper class here.
Phone Book Application
ArrayList
s are especially convenient when you want to maintain a list of your own object types. Let us develop an application that maintains a phone book. Each entry in the phone book contains a name
and a number
along with various methods.
class Entry { private String name; private String number; // constructor public Entry( String n, String num ) { name = n; number = num; } // various methods . . . } |
The program will maintain an ArrayList
of phone book entries. The user will type in a name and get a phone number.
Enter name --> Hal
Name: Hal; Number: 789-1234
Enter name --> Amy
Name: Amy; Number: 123-4567
Enter name --> quit
Question 22:
Suggest some methods that will be useful for
Entry
.
23. Entry Methods
Answer:
String getName()
String getNumber()
boolean equals(Object other)
String toString()
Entry Methods
You may have thought of some additional methods that would be useful in a more realistic example. But for now, use the above methods.
class Entry { private String name; private String number; // constructor public Entry( String n, String num ) { name = n; number = num; } // methods public String getName() { return name ; } public String getNumber() { return number ; } // Compare the name of this Entry with that of some other object public boolean equals( Object other ) { String otherName = ((Entry)other).getName(); // Get name in the other object. return name.equals( otherName ); // Compare name in this object // with that in the other object. } public String toString() { return "Name: " + getName() + "; Number: " + getNumber() ; } } |
The toString()
method of Entry
overrides the toString()
method that all objects have.
Also, the equals(Object)
method of Entry
overrides the equals(Object)
method that all objects have.
Question 23:
Why is the
equals(Object)
method included? Is it really necessary?
24. Testing for Equality
Answer:
We need the equals(Object)
method so the ArrayList
method indexOf()
can be used to search.
Testing for Equality
Examine the equals(Object)
method:
class Entry { private String name; private String number; . . . . . // Compare the name of this Entry with that of some other object public boolean equals( Object other ) { String otherName = ((Entry)other).getName(); // Get the name in the other object. return name.equals( otherName ); // Compare the name in this object // with that in the other object. } . . . . . } |
All classes have an equals(Object)
method because it is defined in the Object
class and all other classes descend from that class.
It might be helpful to look at the Java documentation for class Object
at this point: Object
So all classes have the equals(Object)
method by inheritance. However, most classes override it with a method better suited for their own purpose.
The method expects a parameter of type Object
. This says that the method works with a reference to any type of object. However, our application must compare two Entry
objects with each other. (One entry
holds the name we are searching for; the other is an element of the ArrayList
.) The following
String otherName = ((Entry)other).getName();
uses a type cast to tell the compiler that other
is a reference to an Entry
. This must be done to access the getName()
method of the Entry
object.
Then the name from the other object is compared to the name in the object that contains the equals()
method:
return name.equals( otherName );
If the two names are the same, the method returns true
.
Question 24:
Would the following
equals()
method work as well?class Entry { . . . . . public boolean equals( Object other ) { return name.equals( other.getName() ); } . . . . . }
25. Must Override the Right Method
Answer:
There is an error. getName()
is not a method of Object
.
Must Override the Right Method
You might wonder why the method is not written this way:
public boolean equals( Entry other )
{
return name.equals( other.getName() );
}
This is a correct method, but it does not override the equals(Object)
method. The types of the parameters do not match. To use indexOf()
, you must override the equals(Object)
method:
int indexOf(Object element) // Search for the first occurrence of
//element
, testing for equality
// using the equals(Object) method
// ofelement
.
Question 25:
Will the following work for
equals(Object)
?class Entry { . . . . . public boolean equals( Object other ) { return getName().equals( ((Entry)other).getName() ); } . . . . . }
26. Test Program
Answer:
Yes. The method combines several steps into one statement.
Test Program
import java.util.* ; class Entry { private String name; private String number; // constructor public Entry( String n, String num ) { name = n; number = num; } // methods public String getName() { return name ; } public String getNumber() { return number ; } public boolean equals( Object other ) { return getName().equals( ((Entry)other).getName() ); } public String toString() { return "Name: " + getName() + "; Number: " + getNumber() ; } } public class PhoneBookTest { public static void main ( String[] args) { ArrayList<Entry> phone = new ArrayList<Entry>(); phone.add( new Entry( "Amy", "123-4567") ); phone.add( new Entry( "Bob", "123-6780") ); phone.add( new Entry( "Hal", "789-1234") ); phone.add( new Entry( "Deb", "789-4457") ); phone.add( new Entry( "Zoe", "446-0210") ); // Look for Hal in phone. The indexOf() method uses the // equals(Object) method of each object in the list. Entry target = new Entry( "Hal", null ); int spot = phone.indexOf( target ) ; System.out.println( "indexOf returns: " + spot ) ; } } |
phone
is a list of Entry
references. The program searches that list for "Hal" .
It does so by creating a target Entry
with "Hal" for the name, but null for the phone number. Then the indexOf()
method of phone
looks for a match.
The indexOf()
method uses equals()
to compare successive objects in the list with the target object. Because equals()
looks only at the name
of the two entries, the null in the target object does not matter.
Question 26:
What will the program write?
27. Test Program
Answer:
Yes. The method combines several steps into one statement.
Test Program
import java.util.* ; class Entry { private String name; private String number; // constructor public Entry( String n, String num ) { name = n; number = num; } // methods public String getName() { return name ; } public String getNumber() { return number ; } public boolean equals( Object other ) { return getName().equals( ((Entry)other).getName() ); } public String toString() { return "Name: " + getName() + "; Number: " + getNumber() ; } } public class PhoneBookTest { public static void main ( String[] args) { ArrayList<Entry> phone = new ArrayList<Entry>(); phone.add( new Entry( "Amy", "123-4567") ); phone.add( new Entry( "Bob", "123-6780") ); phone.add( new Entry( "Hal", "789-1234") ); phone.add( new Entry( "Deb", "789-4457") ); phone.add( new Entry( "Zoe", "446-0210") ); // Look for Hal in phone. The indexOf() method uses the // equals(Object) method of each object in the list. Entry target = new Entry( "Hal", null ); int spot = phone.indexOf( target ) ; System.out.println( "indexOf returns: " + spot ) ; } } |
phone
is a list of Entry
references. The program searches that list for "Hal" .
It does so by creating a target Entry
with "Hal" for the name, but null for the phone number. Then the indexOf()
method of phone
looks for a match.
The indexOf()
method uses equals()
to compare successive objects in the list with the target object. Because equals()
looks only at the name
of the two entries, the null in the target object does not matter.
Question 26:
What will the program write?
28. Details
Answer:
indexOf returns 2
Details
Things are getting a little complicated. It would be good to look at some details.
- An
ArrayList
of entries is constructed - Several
Entry
objects are put into the list. - A target
Entry
object is created. - The
indexOf()
searches for the target in the list.- The
equals(Object)
method ofEntry
is used. - The picture shows the third comparison (which returns true).
- The
- A match is found at cell number 2
The indexOf(Object)
method is a member of the ArrayList
, but it uses the equals(Object)
method of Entry
.
Question 27:
Would playing with the program help?
29. Playful Program
Answer:
Of course. Playing with things always helps to understand them.
Playful Program
import java.util.* ; class Entry { private String name; private String number; // constructor public Entry( String n, String num ) { name = n; number = num; } // methods public String getName() { return name ; } public String getNumber() { return number ; } public boolean equals( Object other ) { System.out.print (" Compare " + other + " To " + this ); System.out.println(" Result: " + name.equals( ((Entry)other).name ) ); return getName().equals( ((Entry)other).getName() ); } public String toString() { return "Name: " + getName() + "; Number: " + getNumber() ; } } public class PhoneBookTest { public static void main ( String[] args) { ArrayList<Entry> phone = new ArrayList<Entry>(); phone.add( new Entry( "Amy", "123-4567") ); phone.add( new Entry( "Bob", "123-6780") ); phone.add( new Entry( "Hal", "789-1234") ); phone.add( new Entry( "Deb", "789-4457") ); phone.add( new Entry( "Zoe", "446-0210") ); // Look for Hal in phone. The indexOf() method uses the // equals(Object) method of each object in the list. // System.out.println("Begin Search" ); Entry target = new Entry( "Hal", null ); int spot = phone.indexOf( target ) ; System.out.println("End Search" ); System.out.println( "indexOf returns: " + spot ) ; } } |
Question 28:
Could the program be altered so that it searches for a name entered by the user?
(It would be good practice for you to do this before you go on.)
30. Improved Program
Answer:
Of course. And I am sure that you have already done this.
Improved Program
. . . public class PhoneBookTest { public static void main ( String[] args) { ArrayList<Entry> phone = new ArrayList<Entry>(); phone.add( new Entry( "Amy", "123-4567") ); phone.add( new Entry( "Bob", "123-6780") ); phone.add( new Entry( "Hal", "789-1234") ); phone.add( new Entry( "Deb", "789-4457") ); phone.add( new Entry( "Zoe", "446-0210") ); String name; Scanner scan = new Scanner( System.in ); System.out.print("Enter name -->"); name = scan.next(); while( !name.equals("quit" ) ) { int spot = phone.indexOf( new Entry( name, null ) ) ; if ( spot >= 0 ) System.out.println( phone.elementAt( spot ) ) ; else System.out.println( name + " not found" ) ; System.out.println(); System.out.print("Enter name -->") ; name = scan.next(); } } } |
COf course, this is only a small example and not a practical program. But it uses techniques found in many industrial-strength programs.
Question 29:
The program would be more practical if the user had more freedom in entering the target name. For example, the user should be able
to enter all lower case or all upper case. Where would you make a change to the program to allow this?
31. null as an Element
Answer:
The equals(Object)
method could be made case insensitive.
Another good modification of the program would be to allow the user to put new entries into the list.
null
as an Element
null
as an Element
ArrayList
element can be an object reference or the value null
. When a cell contains null
, the cell is not considered to be empty. The picture shows empty cells with an "X" and cells that contain a null with null
.
import java.util.* ; public class ArrayListEgFive { public static void main ( String[] args) { // Create an ArrayList that holds references to String ArrayList<String> names = new ArrayList<String>(); // Add three Object references and two nulls names.add("Amy"); names.add(null); names.add("Bob"); names.add(null); names.add("Cindy"); System.out.println("size: " + names.size() ); // Access and print out the Objects for ( int j=0; j<names.size(); j++ ) System.out.println("element " + j + ": " + names.get(j) ); } } |
The program prints out:
size: 5
element 0: Amy
element 1: null
element 2: Bob
element 3: null
element 4: Cindy
The cells that contain null
are not empty, and contribute to the size of the list. It is confusing when null
s are elements of some cells. Don't write your programs to do this unless there is a good reason. A good reason might be that you don't want elements to move to new cells when other elements are deleted. So rather than use remove()
you assign null
to a cell.
Question 30:
If you wish to remove Cindy from the
ArrayList
, should you set that cell tonull
?names.set( 4, null )
32. End of Chapter
Answer:
No. Use the remove()
method, which will not create problematic null
s .
names.remove( 4 );
End of Chapter
You have reached the end this chapter. You may wish to review the following. Click on a subject that interests you to go to where it was discussed.
- ArrayList ArrayList class overview.
- ArrayList, constructors ArrayList constructors.
- ArrayList, capacity Capacity and size of a ArrayList.
- ArrayList, add() add() method.
- ArrayList, set() set() method.
- ArrayList, remove() remove() method.
- ArrayList, indexOf() indexOf() method.
- Iterator interface Iterators
- enhanced for loop Enhanced for loop
- autoboxing Autoboxing
- equals(), used with indexOf() Need to override the equals() method.