In the previous lesson we looked at lists and set.
Using the Pen class in ZooAdministrator
The zoo administrator will keep a record of each pen in the zoo, being one for each of the animal types. In the ZooAdministrator class define these Pen instance variables:
You will now define a private helper method that "acquires" an animal into a pen:
Whenever you have a method that adds to a collection (as above) it is often a good idea to provide a way of reversing the process:
You will now define a private helper method that simulates the acquisition of a few lions by placing them in the lion's pen:
You can now define two similar methods for the other pens:
Now define a createExamplePens() method which instantiates the three Pen instance variables and assigns the relevant animals to them:
You can now invoke the createExamplePens() method at the end of the constructor:
You will now define a public method to simulate feeding time at the zoo. This could be written to iterate over each collection separately, but instead you will combine the three collections into one and then iterate over that:
- In the method body, a new empty collection called
animalsis created - The
addAll()method is invoked on animals to add the objects within each of the pens - The
animalscollection is then iterated over. Note that because theanimalscollection is unsorted you cannot predict the sequence in which the objects will be processed
To see the results of the feedingTime() method you can now invoke it upon the admin object inside the main() method of Experiments:
If you want the animals to be sorted into their natural order, then you can pass the collection into a new TreeSet (which will be sorted). In feedingTime() insert the following statement after the last addAll() statement and before the for-each loop:
- Previously, when instantiating a collection class, you have used empty brackets so that an empty collection is created. Above, however, you can see that it is possible to pass another collection inside the brackets so that the new collection will contain all of the objects in the passed collection. This technique enables you to pass in an unsorted collection and turn it into a sorted collection
To see the sorted results ensure you change the for-each loop to use sortedAnimals instead of animals:
To sort in a different sequence than the natural ordering you can utilise the same Comparator object that was used when sorting arrays, although for a collection it is a two-step process.
Firstly, you need to instantiate an empty TreeSet passing the Comparator object as its argument. This tells the TreeSet how it should sequence any objects subsequently added into it:
Secondly, you can add all of the objects within the unsorted collection into the new sorted collection in one go though its addAll() method:
You can now iterate over sortedAnimals and they will be sorted into the order specified by the Comparator object, which in this case is age and name.
There is one final consideration that needs to be addressed. You will recall the discussion of privacy leaks in Section 4, and the Pen class currently leaks the collection of animals through the getAnimals() method. You can see this if you insert the following statements in, for example, the constructor of ZooAdministrator:
You have now managed to modify the internal contents of the Pen object without going through Pen's add() method, which is supposed to be the only way animals should be added to a pen. You saw in Section 8 the copy constructor technique when returning an instance variable, and that would be a valid way of preventing the privacy leak. You could change the getAnimals() method in Pen as follows to return a new collection which contains the objects of the current collection:
Now, if the client object adds or removed objects from the returned collection it will not affect the collection inside the Pen object. There is an alternative technique you can use with collections which will also prevent client objects from adding or removing at all. This uses a static utility method of the Collections class (note the plural name) called unmodifiableCollection(), which returns a read-only version of the collection specified in its argument. Change the getAnimals() method again:
You will now find that if a client object (such as ZooAdministrator) tries to add or remove objects from the collection returned from getAnimals() then although the program will compile you will receive an UnsupportedOperationException at run-time. If you added the statements to the end of the constructor to see the effects of the privacy leak, then please delete them.
In the next lesson we will look at maps.