Вы находитесь на странице: 1из 14

OOP - exercise 1 – Family Tree

Goals: to exercise, experience

− Interfaces and abstract classes
− Inheritance
− Object-oriented design
− Flexibility in code development
− Iterator, Factory, Template method, Strategy and Decorator design patterns
− Linked list and sorted list data structures.

Submission Deadline: April 1, 2009 (no fooling) 20:00

1 Introduction

In this exercise you will implement a family tree in two stages.

1.You will create a generic reusable infrastructure.
2.You will instantiate that infrastructure and use it for the application of your choice
(here it will be your family tree).
The design below is a bit simplistic, and will not provide a complete application, but this is only an

The root of the code will be in a package called oop.ex1. Most of the code will be in packages of the
form oop.ex1.<name>, as described below.

2 Infrastructure (in package oop.ex1.collection)

In this part, you are to define generic interfaces and classes for several data structures, as well as a class
for comparing the efficiency of the different implementations. The main interface for the data structure
provides the contract that the classes need to satisfy. The classes will provide two structures – a linked
list and a sorted linked list. All the code (interfaces and classes) dealing with the data structures will be
in the package oop.ex1.collection and the test in oop.ex1.test.collection.

OOP - exercise 1 – Family Tree: page 1 of 14

Class hierarchy of our data structures:

Sequence Abstract Simple Sorted

Sequence Sequence Sequence

The public interfaces and classes in this package will be visible outside the package; those that are
defined without an access restriction (i.e., have package visibility) will be visible only inside the
package. The above also applies to visibility of methods: when access restriction is not specified for
interface methods, they are implicitly public, but object methods without an access restriction are
“package protected”. Always define your classes and methods with minimum sufficient visibility.

2.1 Define Sequence interface

Objects which sole purpose is to contain other objects are called in Java terminology “collections”.
Java provides several collection implementations in java.util package, but in this exercise we will create
and use our own implementations. One example of collection is a sequence – series of objects stored in
a particular order.

Since we want to define what the sequence does, rather than how it's done, we will start with defining
a Sequence interface which extends java.lang.Iterable and looks like this:
public interface Sequence extends Iterable {
Object first();
boolean isEmpty();
int size();
Object add(Object obj);
Object get(Object obj);
void addMany(Object... objects);
void addAll(Iterable objects);
Defining an interface includes adding appropriate documentation (Javadoc) – requirements described
textually below must be written in the documentation.

All methods in interfaces are implicitly public and abstract. Here's what the above methods should do:
● first() method return the first element of the sequence,
● isEmpty() tests whether sequence has any elements,
● size() returns the size of the sequence and zero if it is empty.
● The method add(Object) allows to add elements to the sequence, returning the added element
(or its equivalent, more on that later), and rejects nulls throwing a runtime exception,
● get(Object) returns an object equal to the parameter, if it is found in the sequence, or null
otherwise. If there are duplicate (equal to each other) objects in the sequence, the get method
may return any one of them. The sequence, as we said, should not contain null elements.

OOP - exercise 1 – Family Tree: page 2 of 14

● The addMany and addAll methods are there for user convenience – they allow users to add
multiple elements at once, the three dots (Object...) is called a vararg and it's an alternative
syntax for Object[] that allows user to call this method as addMany(“a”, “b”, “c”) and get it
translated by the compiler to addMany(new Object[] {“a”, “b”, “c”}).

Iterable interface will allow our sequences to be used in for loops, e.g.:
Sequence sequence = ...;
for (Object element : sequence) {
//element variable, at each stage of iteration, represents next element in the sequence
//do whatever you need with element variable in the loop body
The iterator, which is also a design pattern, allows users of the collection to go over its elements,
performing some action for each one. In Java, iterator is represented by java.util.Iterator interface, and a
collection which allows iteration – java.lang.Iterable, defines java.util.Iterator iterator() method. You
will need to implement iterator() method too, and the actual data structure will have to provide a
corresponding Iterator class, a new instance of which this method will return – iterator instances are
not shared between multiple clients.

2.2 AbstractSequence class

You may notice that the convenience addMany/All methods can be implemented using the add(Object)
and do not directly depend on the actual implementation of the sequence. Same can be said about size
and first methods - which can be implemented using the iterator(). While those may not be optimal
implementations, they provide a basis for sub-classes, who can override the default algorithms with
better ones if needed. This is called Template Method design pattern widely used in Object-Oriented
programs and we will exercise it by creating a package-protected abstract AbstractSequence class.

The get method can also be implemented using iterator() but how should we compare objects for
equality? We want to allow sub-classes to control this, and hence provide equal(Object,Object) which
is intended to be overridden by sub-classes. It is defined abstract and has no body, since it is intended
for internal use only we declare it as protected.
public abstract class AbstractSequence implements Sequence {
public int size() {
int count = 0;
for (Object element : this) count ++;
return count;
public void addMany(Object... objects) {
for (Object obj : objects) add(obj);
public Object get(Object obj) ...
public Object first() ...
public void addAll(Iterable objects) ...
protected abstract boolean equal(Object obj1, Object obj2);

The rest of the Sequence and Iterable methods (the ones not declared in AbstractSequence) are
automatically provided by the JVM as abstract methods.

OOP - exercise 1 – Family Tree: page 3 of 14

Can you think of a reasonable default implementation of the equal method? What do you need to
change to add a default implementation of equal(Object,Object) in AbstractSequence? Include your
answers in the README file.

2.3 The SimpleSequence class – a linked list

We have defined an interface, so let's now implement it. One way of implementing a sequence is based
on a linked list. Linked list is a data structure which holds Node objects. The list stores a pointer to
head node (first in the list), and every node stores the element, and the pointer to the next node. The last
node's “next” pointer is null.

When we create a new linked list, it is originally empty – the head pointer points to null. New elements
are added in the beginning of the list, using roughly the following algorithm:
1. Allocate a new node
2. Insert new element into the newly created node
3. Have new node point to old head
4. Update head to point to new node

Create a public class named SimpleSequence which should extend AbstractSequence providing
implementation for the missing methods. It should also override size() method with a more efficient
implementation that returns the size in constant time, and override the first() method. The get method
needs equality comparison, and here it is made using the Object.equals method. This data structure can
contain duplicate elements.

When overriding methods, we add @Override annotation before method modifiers (method modifiers
are public, protected, private, abstract, static, etc.) - this is not mandatory, but highly recommended,
since it allows the Java compiler to detect a misspelling or incorrect signature of overridden methods
that otherwise will likely result in incorrect behavior of our program. (More info on annotations here.)
Iterator: Usually data structures have an additional dedicated class for the iterator. Iterator has access to
internals of the data structure and implements hasNext() and next() method accordingly. To find out
more about iterators in Java, see this tutorial. In this exercise our data structures do not support removal
of elements, therefore our Iterator needs not support the optional remove() method. The convention in
Java is that not-implemented methods throw UnsupportedOperationException, so we implement the
remove() method of the iterator like this:
public void remove() {
throw new UnsupportedOperationException();

More on exceptions: Exceptions allow us to write fail-fast code - the sooner an error is spotted, the
easier it is to find its cause and the better are the chances to correct it. To learn more about exceptions,
see this tutorial. In this part of the exercise we will use several predefined Java exceptions, such as
UnsupportedOperationException, NullPointerException and java.util.NoSuchElementException. These

OOP - exercise 1 – Family Tree: page 4 of 14

exceptions are “runtime”, so the compiler does not require try/catch clause around the code that may
throw them. Use NullPointerException (also abbreviated NPE) to prevent null values from being added
to sequences, and use NoSuchElementException to signal that no element is available, when one is
expected, such as when returning first element of an empty sequence or in case of incorrect usage of
the iterator.

Generics: when looking through Javadoc and other documentation, you may notice things written
within angle brackets, like Iterator<E>. Those are type parameters to classes and methods, also known
as Generics. We will learn Generics later in the course, so in this exercise we won't use them yet. It
means that if you see a method signature which uses a parameter that came from within angle brackets,
but you didn't supply any angle-bracket parameters – the type you should use instead is Object. The
compiler may issue warnings that you are making unchecked calls – this is also caused by ignoring
Generics. To make the warnings go away, add @SuppressWarnings({"unchecked"}) annotation before
method modifiers (it can coexist with @Override annotation, and the order of annotations does not
matter). You are not allowed to use Generics in this exercise.

“Whether the correctness of a piece of software can be guaranteed or not

depends greatly on the structure of the thing made” Edsger W. Dijkstra
So, remember: keep minimum required visibility of your code – any “secondary” classes which are
used to store or access internal structure should not be accessible from outside world.

2.4 The SortedSequence class – linked list that is always sorted

Sometimes we want to access the elements of the sequence in some order, which is determined by the
values, not the order in which they were inserted. One particular usage is accessing the minimum value
in a constant time. For that purpose we will create a variation of SimpleSequence, a public sub-class
named SortedSequence. When instance of SortedSequence is created, it requires a parameter of the
type java.util.Comparator interface. The comparator is used to compare the values which are being
added to the sequence, to the existing sequence values.

Comparator: is an object that encapsulates ordering, the interface consists of a single method:
public interface Comparator {
int compare(Object o1, Object o2);
The compare method compares its two arguments, returning a negative integer, 0, or a positive integer
depending on whether the first argument is less than, equal to, or greater than the second. If either of
the arguments has an inappropriate type for the Comparator, the compare method throws a
ClassCastException. Comparator can be used in the following way:
int low, high ... //or Integer low, high
Comparator comparator = ...
int comparison = comparator.compare(low,high);
if (comparison > 0) //low is greater than high
System.out.println(“invalid range”);
else if (comparison == 0) //low and high are equal
System.out.println(“single value = ” + low);
else //valid range
System.out.println(“range [” + low + “,” + high + “]”);
You can find more details and examples in this tutorial. Comparator is an example of Strategy design
pattern, it provides a “comparison strategy” to our sequence – any new value is placed in the

OOP - exercise 1 – Family Tree: page 5 of 14

appropriate position in the sequence, according to ascending order of the values. The comparator
cannot be null and is set only once (stored with final field modifier).

The equality comparison here is made using the comparator. This data structure can not contain
duplicates (elements considered equal by the comparator), so when user attempts adding a duplicate, it
has no affect on the data structure and matching collection resident is returned by the add method.
What methods of SimpleSequence do you need to override1?

Include your answer in the README file briefly describing what the overridden method does.

You may implement the algorithms using either recursion or regular

loops. Recursive solution will likely be shorter and more readable,
but non-recursive solution will likely run faster on the JVM.

2.6 Testing oop.ex1.collection

Create a class named SequenceTester in oop.ex1.test.collection package, to test the sequences. This
class should add elements, iterate, add more, search for some objects etc. You should be creative and
test as many different scenarios as possible, to make sure that your data structures work correctly. Test
both types of sequence implementations. You can use Integer objects as sequence elements in your
tests, create a Comparator that uses compareTo method from java.util.Comparable interface (the result
of Comparable.compareTo is often regarded as “natural order”, hence the name). The sources given
with this exercise include oop.ex1.test.collection.NaturalOrderComparator, which you can use like
Comparator naturalOrder = NaturalOrderComparator.INSTANCE;

If you need to generate random numbers, you can use nextInt method in java.util.Random like this:
Random r = new Random(); //create instance of Random once per series
final int max = 10; //numbers between 0 and 9 will be generated
int[] randomNumbers = new int[100]; //create array of 100 numbers
for (int i = 0; i < 100; i++) {
randomNumbers[i] = r.nextInt(max); //set the value to a random number between 0 and 9
More examples of using Random can be found here.

We provide you with a basic test for sequences – oop.ex1.test.collection.SequenceSmokeTest,

alongside some utilities that are used in it, like NaturalOrderComparator, SequenceFactory, and others
located under oop.ex1.test and oop.ex1.test.collection packages. After you finish the sequences
implementation, SequenceSmokeTest has to run successfully, producing following output:
Test success rate = 8/8, results:
[simple empty: success,
simple add 1: success,
simple find 1: success,
sorted empty: success,
sorted add 1: success,
sorted find 1: success,
sorted duplicates: success,
sorted sorting: success]

The test you write can, but does not have to, take advantage of any of the supplied utilities.
1 This assignment does not require improving basic implementation of get

OOP - exercise 1 – Family Tree: page 6 of 14

3 Application (in package oop.ex1.family)
The code for the application, in the package oop.ex1.family, includes the following classes.

Person Person Family

Object Exception

Family Missing Invalid

Marriage Information
Member Information
Exception Exception

Override the default toString method in Family, PersonObject, FamilyMember and Marriage to produce
a sensible String representation of each of these objects

3.1 Person interface and PersonObject class

First we will create a public interface that represents a person. The class should have following
members: name, gender (male or female), birth date and death date. All properties have getter methods
- methods of the form getXxx where xxx is the name of property. Name, gender, and birth date cannot
be changed after object creation, while death date can be set using die method that takes a Date. No
death date (null) means the person is still alive.
Person interface should look like this:
public interface Person {
String getName();
Date getBirthDate();
Gender getGender();
Date getDeathDate();
void die(Date d);
boolean isAlive(Date d);

We will also implement the interface with a public PersonObject class. Name, gender and birth date are
mandatory parameters for its constructor, they cannot be null. PersonObject will store the information
in member fields, but not before performing some validations: that mandatory parameters are not null,
birth dated precedes death date, and death isn't modified after it is set.

3.1.1 Gender enum

Is defined like this: public enum Gender {MALE, FEMALE} and it's values can be referenced
as Gender.MALE and Gender.FEMALE (or, with static import before the class, just as MALE and
FEMALE) and Gender can be treated as a regular class name. MALE and FEMALE are the only
instances of Gender, they can be used in if or switch statements for example:
import static oop.ex1.family.Gender.*;
Gender x = ...;
if (x == MALE) ...
To find out more about Java enums check this tutorial.

3.1.2 Exceptions
To deal with invalid inputs, we will create several exceptions dedicated to family affairs. The

OOP - exercise 1 – Family Tree: page 7 of 14

root exception will be abstract class PersonalInformationException extends RuntimeException,
which will copy all the super-class constructors, but declare them as protected ones, preserving
the same signature. Each constructor needs to call the appropriate super constructor like this:
PersonalInformationException(String msg) { super(msg); }
PersonalInformationException should have two concrete sub-classes:
InvalidInformationException and MissingInformationException, with same package protected
constructors. All exception classes should be public.

3.1.3 Working with Dates

We will use java.util.Date class to represent dates. To simplify working with the date, use the
DateUtil class that you can find in the appendix and on course web-site. Use the static methods
in DateUtil to convert dates to strings and vice versa – dates should be in DD/MM/YYYY
format, e.g. 18/06/1942, 01/02/2009. To learn more about dates in Java, refer here.

3.2 Family object

We will model family with the help of public Family, FamilyMember and Marriage classes, and the
sequences we created in part I of the exercise.

Family This is an approximate schema of

head:FamilyMember index: FamilyMember how the data should be organized

FamilyMember Marriage

person: Person wife: FamilyMember startDate: Date

marriages: Marriage husband: FamilyMember endDate: Date

parents: Marriage children: FamilyMember divorced: boolean

family: Family family: Family

FamilyMember will extend a Person and add more functionality to it, such as information on his/her
relatives and the role the person plays in the family, but we'll describe FamilyMember in more detail in
the section 3.3. Let's start with the family:
public class Family {
public Family(Person head) { /* start with a person who is “head of the family” */ }
public FamilyMember getHead() { ... }
public int size() { /* number of family members */ }
public Iterable getAllMembers() { /* list all family members */ }
public FamilyMember find(Person p) { /* find a Person in the family or null*/ }

3.2.1 Using Sequences

Storing marriages in family member, and children in a marriage, is done using Sequence
objects, and we wish to choose the right implementation for each case. For example in case of
list of marriages, the last marriage is probably the most frequently accessed, so it makes sense
to keep the marriages sorted in reverse chronological order.

OOP - exercise 1 – Family Tree: page 8 of 14

Although we could traverse the entire data structure to find a person in the family, this would be
wasteful. When listing family members, if the same person plays several roles in a family
(someone's a son and a husband, etc.), it may create a difficulty. We will once again use a
sequence from the first part of the exercise to serve as an index of family members – it will
provide an additional storage of family members, being updated any time new member is
accepted into the family. Choose a sequence that does not allow duplicates, as we don't want
family member to be indexed twice.

3.2.2 Comparing Persons

Family members, or more generally Persons, can be compared by name – we will assume for
the purpose of this exercise that names are unique. To maintain order inside any family
members sequence, we need to create a comparator that relies on the natural String ordering
(String class already implements Comparable). Create a comparator that relies on natural order
of Persons names (resembling to the way we defined one in section 2.6).

So except for head of the family, how does a person become a family member?

3.2.3 Family - Factory of FamilyMembers

One joins a family by marrying a family
member or getting born to one. But no one
gets into the family without approval! The
family has to accept one to become its
member, and create an association between
the family and newly accepted member.

Our Family maintains its integrity, like any good Object should. One of the things we want to
ensure is that only one FamilyMember object within a family corresponds to a given person – if
the person already is in the family, we will not create new FamilyMember instance, but instead
return an existing one. Logic like that cannot be placed in a constructor, because constructor
always creates new instances, that's why we designate another method for family member
creation – we create an internal (package protected) method in the Family class that is dedicated
to creating family members (Factory design pattern – family is a “factory” of its members).
Every FamilyMember creation should go through this method, and only this method is allowed
to call FamilyMember constructor. Here is how the method should look like:
FamilyMember accept(Person p) {
if (p == null) throw new MissingInformationException("can't accept null");
return (FamilyMember) _index.add(new FamilyMember(this, p));

3.3 FamilyMember object

FamilyMember implements a Person. As we already said, interfaces define “what” but not “how” and
indeed, FamilyMember will implement Person interface, but underneath it will be very different from
PersonObject: instead of saving personal details in dedicated fields, FamilyMember will store a
member of type Person, to which it will delegate all the methods. FamilyMember constructor takes a
Family and Person parameters, stores the instance of Person as a member field, and implements all

OOP - exercise 1 – Family Tree: page 9 of 14

Person methods by delegating the work to the corresponding methods of the Person instance it
contains, like this:
public class FamilyMember implements Person {
private final Person _person;
FamilyMember(Family family, Person person) {
_person = person;
public String getName() {
return _person.getName();
public Date getBirthDate() {
return _person.getBirthDate();
//more fields and more methods are needed - part of the exercise...
In some cases you may need to add extra logic in the overridden methods. FamilyMember will also
have additional methods, related to the “family” affairs, such as marrying, giving birth, retrieving
information about relatives. These methods will internally use the Family instance to which this
member was associated. This is an example of Decorator design pattern (FamilyMember decorates a
PersonObject), that allows, among other things, to share the same Person instance between several
families and have the changes in Person propagate to the families they are in.

3.4 Marriage object

Marriage, like FamilyMember, can be accessed publicly,
but can not be publicly created. This object also points
back at the family it belongs to, contains a pair of family
members and a list of children, while each child is a
family member. Marriage has a beginning and ending
date and it can end in either divorce or death of one of the

3.4.1 MaritalStatus enum

This enumeration should contain SINGLE, MARRIED, DIVORCED and WIDOWED states, and it
should be defined similarly to what we did with Gender.

3.4.2 Comparing marriages

To organize marriages in reverse chronological order inside marriages sequence, we need to
create a comparator that returns the “opposite” value from the natural dates ordering (Date class
already implements Comparable). Create a comparator that relies on natural order of marriage
start dates (resembling the one in section 2.6), then use reverseOrder method in the class
java.util.Collections to transform it into a reverse-order comparator.

Even though comparators return numeric results, don't use them in

arithmetic operations (plus, minus, negative), due to the danger of
overflow. Use boolean operations only - greater, less, equal.

OOP - exercise 1 – Family Tree: page 10 of 14

3.5 Operations
Following operations should be supported in a family – copy this list to your solution README file
and provide name of the class and name of the function you created for each one of them:
● retrieve parents of a family member;
● retrieve all marriages of a family member;
● retrieve all brothers and sisters of a family member, only children of a biological parent should
be considered;
● family member should be able to marry another person, whether that person is already a family
member or not;
● a marriage can be divorced, or end with the death of at least one of the spouses;
● children can be born into a marriage;
● given a date, the marital status of a family member on that date can be retrieved, it is either
single, married, divorced or widowed;
● given a date, the marriage in which a family member was on that date can be retrieved;
● one can test whether family member is available for marriage on a given date (according to his/
her marital status);
● all children of a family member can be retrieved, either per marriage or from all marriages;
● husband and wife can be retrieved from a marriage;
● start and end date can be retrieved from a marriage, and whether the marriage ended in divorce;

You need to implement all these operations, as well as provide string representations for your objects.
Find the right place in the code for each method – keep computations close to the data they operate on
and where the user would expect to find them. Don't repeat computations.

3.5.1 Assumptions and constraints2

These are the assumptions that you can make while coding and should enforce in your
● Person name is unique – there are no 2 people with the same name, a person with the
same name is considered the same person.
● Wife, sister and mother imply that the person is female; father, brother and husband –
● A person needs to be alive to get married.
● Marriage contains one male and one female.
● Marriage can be divorced only once, marriage ends if one of the spouses dies.
● Children can only be born to “active” marriages (the couple was alive and not divorced).
● One cannot marry a first-hand relative (mother, father, sister, brother or child).
● A person can only be born once, to one couple, and die only once (and not before birth).

Reflect these assumptions in the Javadoc documentation of your classes. You should not
implement validations for things not listed above, for example: same person can be
simultaneously married in 2 different families, or have different parents – it's beyond the scope
of the current exercise to prevent that.

3.5.2 Security – control not just what comes in, but also what goes out
While internally we will store elements in sequences, we will not return Sequence, because
2 The guidelines in this exercise are made up for the purpose of teaching object-oriented programming and Java. They do
not represent political, social, or religious views of the OOP course staff or the Hebrew University.

OOP - exercise 1 – Family Tree: page 11 of 14

user might add elements bypassing the container object. Since we only want users to read from
our data structures, we will expose the minimum interface that allows to do that, in our case we
will use java.util.Iterable.

3.6 Test your family

We are almost done. Create a oop.ex1.test.family package and create a FamilyTest file there with a
static main method that will creates a family with at least 10 members and prints them out – names,
gender, birth dates and death dates, number of marriages and number of children. The print-out should
be copied into the solution README.

We provide you with a basic test for family functionality – oop.ex1.test.family.FamilySmokeTest, that
reuses some utilities in oop.ex1.test package. After you finish the family implementation,
FamilySmokeTest has to run successfully, producing following output:
Test success rate = 7/7, results:
[alive person: success,
dead person: success,
family: success,
head of family: success,
members of family: success,
find in family: success,
marriage: success]

The test you write can, but does not have to, make any use of the provided test.

4 Guidelines
In this exercise you may use all interfaces and classes available in java.lang, but no others, except for
classes introduced in class, like java.util.Iterator, java.util.Date, java.util.Comparator and
java.util.Random. In particular, do not use any existing JDK (or other library) implementation of
java.util.Collection. When importing classes, do it per individual class, do not use bulk import
<package>.*. Static methods should also be imported individually, except in enums, where you are
allowed to do static import <enum-class>.*. Also you are allowed to use java.util.Arrays.deepToString
and java.util.Arrays.deepEquals utility methods.
The submission guidelines require that you code runs w/o errors or warnings. Read the submission
guidelines – they are binding! Submit a file named FamilyTree.jar, with the java files of your program
(but NO class files), and a README file. Be sure to follow the submission and styling guidelines of
the OOP course. Before submitting, pass your jar file through the filter ~oop/www/ex1/check_ex1 as
follows: ~oop/www/ex1/check_ex1 ex1.jar.

Using the code provided to you. Below is the list of packages and classes provided to you, some
complete, some are templates for you to add implementation. Do not change the structure of the code:
no renaming or moving of packages, public classes or public methods is allowed.

Tests: you need to make sure that the tests which we supply to you pass. If they don't, it likely indicates
a problem in your code. As for the tests that you have written – they will help you check your code, but
are not going to be tested or run by the course staff, so you are free to implement them as you wish.
Your grade will be affected only by the results of the provided test, and other tests that we (the staff)
have written.

OOP - exercise 1 – Family Tree: page 12 of 14

5 Getting help
The goal of this exercise is not to deal with technical difficulties or struggle with problematic APIs. If
you are stuck on something – ask. There will be two forums accessible from the course home page
(http://www.cs.huji.ac.il/~oop), one for official announcements and one for exchanging information
between students, where course staff will also participate. The announcements and clarifications in the
official forum are binding, so make sure to check the forum frequently, but anything said in the
students' forum should not be treated as an official response. Submission guidelines contain more
details about forums, if you have a private question, submit it to oop@cs.huji.ac.il

6 Grading policies
● Working according to Coding style guidelines - 20%
● Design, README file - 30%
● Correct implementation – 50%

7 References
Data structures
“Introduction to Algorithms, 2nd Edition” by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest and
Clifford Stein (info)
“Data Structures and Algorithms in Java, 4th Edition” by Michael T. Goodrich and Roberto Tamassia (info)

Design patterns
“Design Patterns: Elements of Reusable Object-Oriented Software” by Erich Gamma, Richard Helm, Ralph
Johnson and John Vlissides (info)

On-line documentation: http://java.sun.com/javase/reference/index.jsp
Javadoc http://java.sun.com/j2se/javadoc/
Annotation http://java.sun.com/docs/books/tutorial/java/javaOO/annotations.html
Iterator http://java.sun.com/docs/books/tutorial/collections/interfaces/collection.html#Iterator

OOP - exercise 1 – Family Tree: page 13 of 14

Exception http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html
Comparator http://java.sun.com/docs/books/tutorial/collections/interfaces/order.html
Enum http://java.sun.com/docs/books/tutorial/java/javaOO/enum.html
Date http://java.sun.com/docs/books/tutorial/i18n/format/dateintro.html
Random http://java.sun.com/developer/TechTips/2000/tt1107.html#tip1

OOP - exercise 1 – Family Tree: page 14 of 14