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. 

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
Creative Commons License 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

oldArrayOnce 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.

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

newArrayIn 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.

ArrayListObject

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:

  1. The elements of an ArrayList must be object references, not primitive data like int or double.
  2. 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 an ArrayList can contain only object references. How can you use an ArrayList to store your ints? (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 Strings. 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 Strings. 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

To 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 an ArrayList suitable for this situation.

ArrayList students = new ArrayList( ) ;

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

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

    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 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.

    after3addsimport 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) );
      }
    }

    This program creates an 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:

    What does the program print out?

    size:
    new size:
    element 0: 
    element 1: 
    element 2: 

    12. Setting ArrayList Elements

    
    

    Answer:

    size: 0 new size: 3 element 0: Amy element 1: Bob element 2: Cindy

    Setting 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. 


    import java.util.* ;                
    public class ArrayListEgThree
    {
    
      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 Objects
        for ( int j=0; j<names.size(); j++ )
          System.out.println("element " + j + ": " + names.get(j) );
    
        // Replace "Amy" with "Zoe"
        names.set(0, "Zoe");
        System.out.println();
        
        // Access and print out the Objects
        for ( int j=0; j<names.size(); j++ )
          System.out.println("element " + j + ": " + names.get(j) );
        
      }
    }


    Question 12:

    What does the program print out?

    element 0:
    element 1:
    element 2:
    
    element 0:
    element 1:
    element 2:

    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 at index. Each element with 
    // an index greater than index 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 at index. Each element with an index 
    // greater than index is shifted downward to have an index
    // one smaller than its previous value.
    // Returns a reference to the removed element.
    // Throws an IndexOutOfBoundsException 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.

    fourBooks

    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()

    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

    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 of element. 
    

    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

    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 an Iterator for itself.
        • Iterator<E> interface -- an Iterator 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:

      Iterator visitor = primes.() ;

    18. Enhanced for Loop

    
    

    Answer:

    Iterator <Integer> visitor = primes.iterator() ;

    Enhanced for Loop

    The enhanced for loop (sometimes called a "for each" loop) can be used with any class that implements the 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 and double be added to an ArrayList ?

    19. Wrapper Classes

    
    

    Answer:

    No.

    The non-empty cells of an ArrayList must contain object references (or null).

    Wrapper Classes

    To put an 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.

    ArrayListIntegersimport 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 ints 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

    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

    Here is a program that creates an ArrayList of Integer references. The arguments to add() look like int literals, but at runtime, the ints 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

    ArrayLists 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
    // of element.

    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

    These ideas might be confusing. Here is a program that shows how the pieces fit together. Copy this program to a file, compile it, and run it:

    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

    These ideas might be confusing. Here is a program that shows how how the pieces fit together. Copy this program to a file, compile it, and run it:

    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

    ArrayListPhoneThings are getting a little complicated. It would be good to look at some details.

    1. An ArrayList of entries is constructed
    2. Several Entry objects are put into the list.
    3. target Entry object is created.
    4. The indexOf() searches for the target in the list.
      • The equals(Object) method of Entry is used.
      • The picture shows the third comparison (which returns true).
    5. 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

    Here is the program, just as before, but with some statements added to show what is going on.

    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 ) ;
      }
    }
    Copy the program to a file and run it. Play with it for a while.

    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

    Here is the 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

    An 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.

    nullsInListimport 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 nulls 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 to null?

    names.set( 4, null )

    32. End of Chapter

    
    

    Answer:

    No. Use the remove() method, which will not create problematic nulls .

    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.