Week 6 Answers


  1. Using the "Person" class (that we looked at in week 4), write a program that does:
          // ** a ** 
          for (int i=0; i<20; i++) {
             // Create a new person with random age
             int age = (int) (Math.random() * 70);
             Person p = new Person("Person number " + i, age);
          }
          // ** b **
    
  2. How many "Person"s does this code create?

    20.

  3. Where are they by the time you get to line "b"?

    At the end of each loop iteration, the "p" variable disappears. Since each new object was referenced only via "p", the object becomes eligible for garbage collection. So although the loop creates 20 new objects, there's no guarantee that more than one will exist at any time. Most likely the GC won't run which means after the loop finishes they'll all be in memory somewhere, but since no references to them exist, then you have no way to get at them.

    So at line "b", all you can say is you don't know where they are, or whether they still exist.

  4. At line "a", create a "LinkedList" object called "myCollection". Inside the loop, add each new Person to myCollection.

    The code will now look something like this:

          // ** a ** 
          // Declare the variable
          java.util.LinkedList myCollection;
    
          // Create a new (empty) LinkedList object
          myCollection = new java.util.LinkedList();
    
          for (int i=0; i<20; i++) {
             // Create a new person with random age
             int age = (int) (Math.random() * 70);
             Person p = new Person("Person number " + i, age);
    
             // LinkedList implements the "Collection" interface, which has
             // an "add" method for adding objects
             myCollection.add(p);
          }
          // ** b **
    
  5. Where are all the Person objects now by the time you get to line "b"?

    Since each of them was added to the list, the list will have references to them, and so the garbage collector won't have got rid of them. So long as the "myCollection" variable remains in scope, all of the objects you created should still be around (and accessible via "myCollection").

  6. At line "b", create a new Iterator to fetch each item out of myCollection and print them out.

    Your code will now look something like:

          // ** b **
          java.util.Iterator it;
    
          // The "Collection" interface provides an "iterator" method which
          // provides us with a way to iterate through all elements in the
          // collection
          it = myCollection.iterator();
          while (it.hasNext()) {
              // The "next" method returns an Object
              Object o = it.next();
    
              // This will call the appropriate "toString" method, i.e.
              // the one we've defined for "Person"
              System.out.println(o);
          }
    

    What order do they come out in?

    The objects should get displayed in the same order as they were put into the list, i.e. "Person number 0" ... "Person number 19". This is because the "add" method for a a "LinkedList" appends new items to the list (see the relevant class documentation).

  7. Modify the "Person" class so that the definition now reads:
        class Person implements Comparable { ...
    
    What happens when you try to compile it? What have you got to do to fix this?

    You should get an error from the compiler because you've not got a "compareTo" function defined in the "Person" class. If you say that your class implements "Comparable", you have to create methods in your class that correspond with those declared in that interface.

  8. Fix "Person" so it now compiles as a "Comparable" class.

    You'll need a method "compareTo" in your Person class which will look something like this:

         // The method definition must look exactly the same as the
         // one defined in the "Comparable" interface
         public int compareTo(Object o)
         {
             // We are passed an argument of type "Object", but we need
             // to use some of the fields in it which are specific to
             // "Person", so we have to cast the argument into a Person.
             // At run-time, we'll only be allowed to do this if the
             // argument really is a Person.  We can check that the
             // cast is safe by using "instanceof"
             if (o instanceof Person) {
    
                 // We know it's safe to do this now:
                 Person other = (Person)o;
    
                 // Now we can look at the "age" field inside the
                 // object we've been given, and compare it to the
                 // "age" field in our own object.
                 if (other.age > age) {
                    return 1;
                 }
                 if (other.age == age) {
                    return 0;
                 }
                 return -1; 
             }
             // It wasn't another "Person", this shouldn't ever happen but
             // we'll exit gracefully
             return 0;
         }
    

    Now change your program so that "myCollection" is a "TreeSet". What difference does that make to the results?

    The only change to the main code will be:

          // ** a ** 
          // Declare the variable
          java.util.TreeSet myCollection;
    
          // Create a new (empty) TreeSet object
          myCollection = new java.util.TreeSet();
    
    

    When you run it, you should now see the people displayed in descending order of age.

  9. What is the problem with using "TreeSet" for this program?

    If you wrote the "compareTo" method like I did, then two "Person" objects will be considered to be "equal" if they have the same age. When you add an object to a TreeSet, if it is "equal" to another object in the set, then the first object will be removed and replaced by the second. So it's likely that the TreeSet won't contain all of the objects that were created.

    How would you fix this?

    To fix this, the "compareTo" function should do more than just compare ages.

  10. Implement the fix described in the previous answer

    Here is a better version of "compareTo":

        public int compareTo(Object o) 
        {
            if (o instanceof Person) {
                Person other = (Person)o;
                if (other.age > age) {
                    return 1;
                }
                if (other.age < age) {
                    return -1;
                }
            }
    
            // The object wasn't a Person, or it was
            // a Person with the same age.  So we'll use
            // the hashcode to make the decision
    
            if (o.hashCode() == hashCode()) {
                // They are the same object
                return 0;
            }
             
            if (o.hashCode() > hashCode())  {
                return 1;
            }
            return -1;
        }
        
        
    

Back to index page