The Java Collections Framework
Understanding the Array List data structure
Mutating Array List
Generating Javadocs
Binary Search
Visitors
Version: 5.2.1

Lab 8

Goals: The goals of this lab is to learn how to work with mutable direct access data types defined in the Java Collections Framework library.

The Java Collections Framework

Start the lab by looking at the web pages for the Java Libraries APIs. Scroll through the All Classes in the lower left frame to find the Comparable and Comparator interfaces. You can see from the descriptions that there is a lot of detail, much more than we would expect from such a simple function-object. We will address some of these issues in the lectures.

Scroll through the All Classes frame on the left again and find the ArrayList class. In lecture we have discussed a number of methods we can use to modify/manipulate and instance of ArrayList. Use the online documentation as you work on this part of the lab.

Understanding the ArrayList data structure

For this part of the lab download the file ExamplesArrayList.java, which contains two classes: the ExamplesArrayList class and the Person class. Start a new project, Lab8-ArayLists and import this file into it. Your goal in this part of the lab is to design a test suite for the methods defined for the Arraylist.

Mutating ArrayList

Continue with the current project and test suite.

Generating Javadocs

Spend a few minutes learning how to generate web pages of your documentation for this project. Notice that we have already started to write all purpose statements and comments using the JavaDoc format.

Under the Project menu select Generate Javadoc and then select the files that should be used to generate the documentation (likely your entire project). By convention we typically generate JavaDoc files into a directory named docs at the same level as the src directory.

Be sure to fix any warnings and problems with the generation.

Binary Search

This problem will be a part fo the homework assignment, but you should start working on it now.

Start with a new project HW08Problem1 and create two files: Algorithms.java and ExamplesAlgorithms.java.

Visitors

We often do not know what kinds of methods the programmers need to define for their lists of objects. Furthermore, they may have to define one specific method for their list that is not applicable to any other list of objects.

For example, we may want to use these classes for our circularly defined data. So we may want to add the method addBook to the classes that represent the list of authors (or addRole to the classes that represent the list of movie actors).

To make the library extensible, the designers need to provide ways for adding new methods at the time the programmer wants to use it.

One way to make the self-referential union of classes extensible is by defining a visitor interface and adding to the union a method that invokes the methods of the visitor interface supplying its own internal data as arguments. This sounds very complicated. We will illustrate this on an example.

Start with a new project HW08Problem2 and add to it all files in from Lab8-Visitors.zip. You should have the following files:

Book.java

Song.java

Image.java

ILo.java

ISelect.java

ExamplesLists.java

NoSuchElementException.java

ILoVisitor.java

Here is an example of a visitor interface for the classes that define a list of objects:

// A visitor for the ILo<T> classes that

// consumes no arguments

// and produces the result of the type R

interface ILoVisitor<R, T>{

  // method for the empty list

  public R forMt();

 

  // method for the nonempty list

  public R forCons(T first, ILo rest);

}

The visitor for a union of data types contains one method for every class in the union, and has the name that indicates the class it targets. The arguments for each method are the fields in the target class that are needed to perform any operations on an object in this field. So, here, the method forMt takes no arguments, as there are no relevant fields in the class MtLo<T>. On the other hand, the method forCons consumes two arguments: first and rest, where the first is of the type T and the rest is of the type ConsLo<T>.

We now add to the classes MtLo<T> and ConsLo<T> the hooks, the methods that accept the instance of the visitor class and invoke the appropriate methods defined there:

// in the interface ILo<T>:

// accept the visitor that produces a result of the type R

public <R> R accept(ILoVisitor<R, T> ilov);

 

// in the class MtLo< T>:

// accept the visitor that produces a result of the type R

public <R> R accept(ILoVisitor<R, T> ilov){

  return ilov.forMtLo();

}

 

// in the class MtLo< T>:

// accept the visitor that produces a result of the type R

public <R> R accept(ILoVisitor<R, T> ilov){

  return ilov.forConsLo(this.first, this.rest);

}

The example included in the Lab8.zip files defines a visitor that represents a method that computes the total download time for all files in the list of image files.

The visitor class (that implements the ILoVisitor<T> interface is defined as follows:

// A visitor that computes the total download time for all files

// in the list of image files

class ILoImageDownloadTimeVisitor

  implements ILoVisitor<Integer, Image>{

 

  int speed;

  ILoImageDownloadTimeVisitor(int speed){

    this.speed = speed;

  }

 

  // method for the empty list

  public Integer forMt(){

    return 0;

  }

 

  // method for the nonempty list

  public Integer forCons(Image first, ILo rest){

    return

        first.fileSize / speed + rest.accept(this);

  }

}

The following examples show how we can use this method with our lists of data:

ILoVisitor imageDownloads =

        new ILoImageDownloadTimeVisitor(200);

 

// test the use of the ILoMakeStringVisitor

void testILoMakeStringVisitor(Tester t){

  t.checkExpect(this.mtloi.accept(this.imageDownloads), 0);

  t.checkExpect(this.ilist2.accept(this.imageDownloads), 287);

}

We see that the methods defined in the class that implements the visitor have the same structure as those originally defined inside of the MtLo... and ConsLo... classes. The instance of the list then invokes the new method by applying the accept method with the appropriate visitor as its argument.

We could now rewrite the solution to the circularly referential problem af books and authors (or actors with movie roles) using the generic list of objects and adding the appropriate visitor to the list of authors (or actors). Work this out on your own as a practice problem - it is not a required part.

You will finish this problem as a part of your next homework.