EECS1030Z Test 3

Thursday February 26, 2015, 14:30-15:45
Lab 01
Version G


Programming question

Implement the Interval class having the API shown here. A skeleton can be found here.

package test3;
import java.util.HashMap;
import java.util.Map;

/**
 * A class that represents an interval of values on the integer number line. An
 * interval has two properties: a <code>minimum</code> value and a
 * <code>maximum</code> value. Interval instances always ensure that the
 * following class invariant is true:
 * 
 * <p>
 * <code>minimum <= maximum</code>
 * 
 * <p>
 * Clients request <code>Interval</code> instances using the static method
 * <code>Interval.getInstance</code>. The class ensures that only one
 * <code>Interval</code> instance exists for each unique minimum-maximum pair.
 * Repeated calls to <code>Interval.getInstance</code> using the same minimum
 * and maximum values always return a reference to the same object; that is to
 * say:
 * 
 * <p>
 * <code>Interval.getInstance(1, 10) == Interval.getInstance(1, 10)</code> is
 * always <code>true</code>.
 * 
 * @author EECS1030Z_2014_15W
 * 
 */
public class Interval {

  private static Map<String, Interval> instances = new HashMap<String, Interval>();
  private int min;
  private int max;

  /**
   * Create an interval with the specified minimum and maximum values.
   * 
   * @param min
   *          the minimum value of the interval
   * @param max
   *          the maximum value of the interval
   * @throws IllegalArgumentException
   *           if <code>min > max</code>
   */
  private Interval(int min, int max) {
    if (min > max) {
      throw new IllegalArgumentException("min > max");
    }
    this.min = min;
    this.max = max;
  }

  /**
   * Get the interval having the desired minimum and maximum values.
   * 
   * @param min
   *          the minimum value of the interval
   * @param max
   *          the maximum value of the interval
   * @return the interval (min, max)
   * @throws IllegalArgumentException
   *           if <code>min > max</code>
   */
  public static Interval getInstance(int min, int max) {
    String key = min + "," + max;
    Interval i = Interval.instances.get(key);
    if (i == null) {
      i = new Interval(min, max);
      Interval.instances.put(key, i);
    }
    return i;
  }

  /**
   * Returns the minimum value of the interval
   * 
   * @return the minimum value of the interval
   */
  public int getMinimum() {
    return this.min;
  }

  /**
   * Returns the maximum value of the interval
   * 
   * @return the maximum value of the interval
   */
  public int getMaximum() {
    return this.max;
  }

  /**
   * Checks if <code>value</code> is inside this interval. A value is considered
   * inside this interval if both
   * 
   * <p>
   * <code>value >= minimum</code> and <code>value <= maximum</code>
   * 
   * <p>
   * are true.
   * 
   * @param value
   *          the value to check
   * @return <code>true</code> if <code>value</code> is inside this interval,
   *         <code>false</code> otherwise
   */
  public boolean contains(int value) {
    return (value >= this.getMinimum()) && (value <= this.getMaximum());
  }

  /**
   * Return the width of this interval. The width of an interval is defined as
   * the maximum value of the interval minus the minimum value of the interval.
   * 
   * @return the width of this interval
   */
  public long width() {
    return (long) this.getMaximum() - this.getMinimum();
  }

  /**
   * Return a new interval that contains the two given intervals. The width of
   * the new interval will be as small as possible. For example, if the two
   * intervals to be contained are: <code>[-1, 1]</code> and
   * <code>[10, 12]</code> then the new interval returned by this method is
   * <code>[-1, 12]</code>.
   * 
   * 
   * @param a
   *          an interval to be contained by the new interval
   * @param b
   *          the other interval to be contained by the new interval
   * @return a new interval that contains both intervals <code>a</code> and
   *         <code>b</code>
   */
  public static Interval containingInterval(Interval a, Interval b) {
    int min = Math.min(a.getMinimum(), b.getMinimum());
    int max = Math.max(a.getMaximum(), b.getMaximum());
    return new Interval(min, max);
  }

  /**
   * Returns the string representation of this interval. The string contains the
   * minimum and maximum values separated by a comma and space all inside of a
   * pair of square brackets. For example, the string
   * 
   * <p>
   * <code>[-5, 8]</code>
   * 
   * <p>
   * represents the interval whose minimum value is <code>-5</code> and whose
   * maximum value is <code>8</code>
   * 
   * @return a string representation of the interval
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return "(" + this.getMinimum() + ", " + this.getMaximum() + ")";
  }
}

Other questions

Question 1

What term best describes an aggregation relationship?

A. has-a
B. is-a
C. owns-a
D. uses-a

Question 2

Consider the following class X:

public class X {
  private Interval interval;
  
  public X(int min, int max) {
    this.interval = Interval.getInstance(min, max);
  }
  
  public Interval getInterval() {
    // implementation not shown
  }
}

Suppose that a client writes the following main method that uses X:

public static void main(String[] args) {
  X x = new X(1, 5);
  X y = new X(1, 5);
  X z = new X(10, 50);
  Interval i = z.getInterval();
  // HERE
  
  // remainder of main method not shown
}

How many Interval objects are in memory when the main method reaches the line with the comment HERE?

A. 1
B. 2 (x and y are the same Interval object, z is the second Interval object)
C. 3
D. 4

Question 3

The Interval method named getInstance resembles a constructor in that it returns a reference to a new Interval object; what name is given to a method like getInstance that returns a reference to a newly created object?

Type your answer here: static factory method

Question 4

What single word explains why the Interval method named width returns a long value instead of an int value?

Type your answer here: overflow (the value of (this.maximum - this.minimum) can be bigger than Integer.MAX_VALUE)

Question 5

Suppose that we override equals for Interval so that two intervals are equal if and only if their minimum values are equal and their maximum values are equal. Normally, we would also override hashCode, but do we have override hashCode for Interval? Explain why or why not.


No. Interval is a multiton which means that there is exactly one Interval object for each unique min-max pair. The only way that two Intervals can be equal is if they are the same object, so the Object version of hashCode (which uses the object address) is sufficient.


Question 6

Suppose that we modifed the Interval class so that it provided methods to change the minimum and maximum value of the interval:

public boolean setMinimum(int min) {
  boolean minChanged = false;
  if (min <= this.getMaximum()) {
    this.minimum = min;
    minChanged = true;
  }
  return minChanged;
}

public boolean setMaximum(int max) {
  boolean maxChanged = false;
  if (max >= this.getMinimum()) {
    this.maximum = max;
    maxChanged = true;
  }
  return maxChanged;
}

Explain why you think adding these two methods to Interval is a good or bad idea.


This is a bad idea because the state of an Interval can now be changed, which makes it possible for there to be more than one Interval object for any given min-max pair.