Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

CS46B Homework 3: Basic Java Classes Getting started Create a new workspace dire

ID: 3869923 • Letter: C

Question

CS46B Homework 3: Basic Java Classes

Getting started

Create a new workspace directory, or use an existing one. Create a Java project
called hw3proj in the workspace. Create a package called movies in the project.
All classes and interfaces that you create should go in the movies package.

Class movie
Create a public class Movie with private instance variables String title
and int year. The class should declare that it implements the
Comparable interface, and should provide the following:
• A constructor that takes 2 arguments: a String and an int (in that order)
for initializing title and year.
• A method that satisfies the Comparable interface. Movies
should be compared first by title and then by year.
• Methods getTitle() and getYear() that do the right thing.
• An equals() method that is compatible with the method that satisfies the
Comparable interface.
• A toString() method that returns “Movie” followed by 1 space followed
by the title followed by 1 space followed by open-parenthesis followed
by the year followed by close-parenthesis. Example: Movie The Maltese Falcon (1941)
• A public static method getTestMovies(), which returns an array of 10
unique Movie instances. They don’t have to be real movies – it’s ok to
make them up. The 0th and 1st array elements must be 2 movies with the
same title but from different years (e.g. The Thomas Crown Affair 1968
and The Thomas Crown Affair 1999, or True Grit 1969 and True Grit
2010). The 2nd and 3rd elements (counting from 0) must be 2 movies with
different titles but from the same year (e.g. The Martian 2015 and Bridge
of Spies 2015). The 4th and 5th elements must be 2 different objects that
represent the same movie (same title and same year). The remaining
elements can be any movies you like.
• A hashCode() method. Use the following:
public int hashCode()
{
return title.hashCode() + year;
}

Interface FilmArchive
Create an interface called FilmArchive that defines 2 methods:
• getSorted(), which takes no args and returns ArrayList.
Implementations should return an array list whose members are unique
according to deep equality, and sorted according to the criteria in
Movie’s compareTo() method.
• add(), which takes one arg of type Movie and returns a boolean. If add()
is called where the arg already appears in the film archive, the method
should return false and otherwise do nothing; if the arg of add() does not
yet appear in the archive, it should be added as described below and the
method should return true.

3 implementing classes
Create 3 classes, named ListFilmArchive, HashFilmArchive, and
TreeFilmArchive, that implement the FilmArchive interface.

Class ListFilmArchive
This class should extend ArrayList. In your add() method, check every
movie in the array list for deep equality to the arg of add(). If you find a movie
that “equals()” the arg, just return false; if you don’t find one, add the arg to the
array list and return true.
Hint: you are overriding the add() method inherited from the ArrayList
superclass. When you detect that the arg movie doesn’t appear in the array list,
you want to call the superclass’ version of add(). To do that, use something like
this line:
boolean reallyAdded = super.add(aMovie);
“super.” in this overridden method tells Java “please use the version of add in
my superclass”.
For the getSorted() method, use a TreeSet to do the sorting. First
construct a TreeSet, passing the ArrayList into the TreeSet
constructor; since ListFilmArchive “isa” ArrayList, “this” is a reference
to the ArrayList that you want to pass. Then construct and return a new
ArrayList, passing the TreeSet into the ArrayList constructor; when
that ArrayList is constructed, the movies in the TreeSet will be added to it one
by one, in the TreeSet’s natural order, which is the order that you want. In
other words, this long paragraph describes 2 simple lines of code.

Class HashFilmArchive
This class should extend HashSet. It’s ok to add movies to a HashSet
because Movie has mutually compatible equals(), and hashCode() methods.
For the add() method, first read the documentation for add() in the
java.util.HashSet API page
(https://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html ).
Convince yourself that this method does exactly what add() in
HashFilmArchive should do. Since the inherited method is acceptable, you
don’t need to create add() in HashFilmArchive. (But you do need to understand
why you don’t need to).
For the getSorted() method, do something similar to what you did in
ListFilmArchive.

Class TreeFilmArchive
This class should extend TreeSet.
For the add() method, first read the documentation for add() in the API page
for java.util.TreeSet
(https://docs.oracle.com/javase/8/docs/api/java/util/TreeSet.html ).
Convince yourself that this method does exactly what add() in
TreeFilmArchive should do. Since the inherited method is acceptable, you don’t
need to create add() in TreeFilmArchive.
For the getSorted() method, do something somewhat similar to, but simpler
than, what you did in ListFilmArchive and HashFilmArchive. All you need to do
is construct an ArrayList, passing “this” into the ArrayList ctor. Well,
that’s not all you need to do … you also need to understand why it works.

Testing your 3 FilmArchive classes
You already have test inputs: the array returned by Movie.getTestMovies(). Be
sure that this array meets the requirements described above.
To test the ListFilmArchive class, add the following main() method:
public static void main(String[] args)
{
ListFilmArchive archive = new ListFilmArchive();
for (Movie m: Movie.getTestMovies())
archive.add(m);
for (Movie m: archive)
System.out.println(m);
System.out.println("**************");
for (Movie m: archive.getSorted())
System.out.println(m);
}
If you get a compiler error on the line that prints out a row of stars, delete the
quote signs and then type them back in. Some systems do weird things with
smart quotes. Stupid smart quotes!
Run ListFilmArchive as an app. Look at the number of movies that were
printed out, and their order. Are these what you expected?
To test HashFilmArchive, add the same main() to HashFilmArchive but change
“ListFilmArchive” to “HashFilmArchive”. Then add the HashFilmArchive main()
to TreeFilmArchive but change “HashFilmArchive” to “TreeFilmArchive”. This
is a common way to test individual classes in Java: you give each class a main()
method that tests just that class.

Let’s do science
Create the following class:
package movies;
public class HashAnalyzer
{
public static void main(String[] args)
  {
      HashFilmArchive archive = new HashFilmArchive();
      for (int i=0; i<100000; i++)
      {
          archive.add(new Movie("Movie" + i, 2017));
          if (i%1000 == 0)
              System.out.println(i);
      }
      System.out.println("DONE");
  }
}
The main() method creates 100,000 fake movies and puts them into a
HashFilmArchive. Every 1000 insertions, it prints out a message. When you
run the app, the time interval between messages will give you feedback about
time performance of the add() method of HashFilmArchive.


Create a second analyzer class called ListAnalyzer. It should be just like
HashAnalyzer, except it should use a ListFilmArchive.

Explanation / Answer

FilmArchieve.java:

package movies;

import java.util.ArrayList;

import movies.Movie;
public interface FilmArchive {
public ArrayList<Movie> getSorted();
public boolean add(Movie m);
}


ListAnalyzer.java:

package movies;

import movies.ListFilmArchive;
import movies.Movie;

public class ListAnalyzer {
public static void main(String[] args) {
ListFilmArchive archive = new ListFilmArchive();
for (int i = 0; i < 100000; i++) {
archive.add(new Movie("Movie" + i, 2017));
if (i%1000 == 0)
System.out.println(i);
}
}
}

HashAnalyzer.java:

package movies;

import movies.HashFilmArchive;
import movies.Movie;

public class HashAnalyzer {
public static void main(String[] args) {
HashFilmArchive archive = new HashFilmArchive();
for (int i=0; i<100000; i++) {
archive.add(new Movie("Movie" + i, 2017));
if (i%1000 == 0)
System.out.println(i);
}
}
}


Movie.java:

package movies;

public class Movie implements Comparable<Movie>{
private String title;
private int year;
public Movie(String title, int year) {
this.title = title;
this.year = year;
}
public String getTitle() {
return title;
}
public int getYear() {
return year;
}
public boolean equals(Object x) {
Movie that = (Movie)x;
return this.compareTo(that) == 0;
}
public int compareTo(Movie that) {
int titleCmp = this.title.compareTo(that.title);
if (titleCmp != 0) {
return titleCmp;
}
if (this.year < that.year) {
return -1;
}
else if (this.year == that.year) {
return 0;
}
else {
return 1;
}
}
public String toString() {
return "Movie " + title + " (" + year + ")";
}
public static Movie[] getTestMovies() {
Movie[] allMovies = new Movie[10];
allMovies[0] = new Movie("Aladdin", 1968);
allMovies[1] = new Movie("Aladdin", 1956);
allMovies[2] = new Movie("Mr.Penguin", 1977);
allMovies[3] = new Movie("Fremont", 1977);
allMovies[4] = new Movie("The Parent Trap", 1998);
allMovies[5] = new Movie("The Parent Trap", 1998);
allMovies[6] = new Movie("The Intern", 2015);
allMovies[7] = new Movie("Tangled", 2013);
allMovies[8] = new Movie("Up", 2008);
allMovies[9] = new Movie("Pride & Prejudice", 2003);
return allMovies;
}
public int hashCode() {
return title.hashCode() + year;
}
}


TreeFilmArchieve.java:

package movies;

import java.util.TreeSet;

import java.util.ArrayList;

import movies.FilmArchive;

import movies.Movie;

public class TreeFilmArchive extends TreeSet<Movie> implements FilmArchive {

public ArrayList<Movie> getSorted() {

ArrayList<Movie> movies = new ArrayList<Movie>(this);

return movies;

}

public static void main(String[] args) {

TreeFilmArchive archive = new TreeFilmArchive();

for (Movie m : Movie.getTestMovies())

archive.add(m);

for (Movie m : archive)

System.out.println(m);

}

}


ListFilmArchieve.java:

package movies;

import java.util.ArrayList;

import java.util.TreeSet;

import movies.FilmArchive;

import movies.Movie;

public class ListFilmArchive extends ArrayList<Movie> implements FilmArchive {

public boolean add(Movie that) {

for (Movie m : this) {

if (m.getYear() == that.getYear()

&& m.getTitle().equals(that.getTitle())) {

return false;

}

}

super.add(that);

return true;

}

public ArrayList<Movie> getSorted() {

TreeSet<Movie> tree = new TreeSet<Movie>(this);

ArrayList<Movie> someMovies = new ArrayList<Movie>(tree);

return someMovies;

}

public static void main(String[] args) {

ListFilmArchive archive = new ListFilmArchive();

for (Movie m : Movie.getTestMovies())

archive.add(m);

for (Movie m : archive)

System.out.println(m);

}

}


HashFilmArchive.java:

package movies;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.TreeSet;

import movies.FilmArchive;
import movies.Movie;
public class HashFilmArchive extends HashSet<Movie> implements FilmArchive {
public ArrayList<Movie> getSorted() {
HashSet<Movie> hashy = new HashSet<Movie>(this);
ArrayList<Movie> someMovies = new ArrayList<Movie>(hashy);
return someMovies;
}
public static void main(String[] args) {
HashFilmArchive archive = new HashFilmArchive(); for (Movie m: Movie.getTestMovies())
archive.add(m);
for (Movie m: archive) System.out.println(m);
}
}