Das Designprinzip der Collection-Klassen folgt drei Stufen:
- Schnittstellen legen Gruppen von Operationen für die verschiedenen Behältertypen fest.
- Abstrakte Basisklassen führen die Operationen der Schnittstellen auf eine minimale Zahl von als abstrakt deklarierten Grundoperationen zurück, etwa addAll() auf add() oder isEmpty() auf getSize().
- Konkrete Klassen für bestimmte Behältertypen beerben die entsprechende abstrakte Basisklasse und ergänzen die unbedingt erforderlichen Grundoperationen (und einige die Performance steigernde Abkürzungen gegenüber der allgemeinen Lösung in der Oberklasse).
Es gibt eine Reihe von abstrakten Basisklassen, die den Containern eine Basisfunktionalität geben. Unter ihnen sind:
AbstractCollection
Implementiert die Methoden der Schnittstelle Collection ohne iterator() und size(). AbstractCollection ist Basisklasse von AbstractList und AbstractSet.
AbstractList
Erweitert AbstractCollection und implementiert die Schnittstelle List. Für eine konkrete Klasse müssen lediglich Methoden für get(int index) und size() implementiert werden. Soll die Liste auch Elemente aufnehmen, sollte sie auch set(int index, Object element) implementieren. Andernfalls bewirkt das Einfügen von Elementen nur eine Unsupported OperationException. Die direkten Unterklassen sind AbstractSequentialList, ArrayList und Vector.
AbstractSequentialList
AbstractSequentialList erweitert AbstractList (und damit auch AbstractCollection) und bildet die Grundlage für die Klasse LinkedList. Im Gegensatz zur konkreten Klasse ArrayList bereitet AbstractSequentialList die Klasse LinkedList darauf vor, die Elemente in einer Liste zu verwalten und nicht wie ArrayList in einem internen Array.
AbstractSet
Erweitert AbstractCollection und implementiert die Schnittstelle Set. Die Klasse AbstractSet dient als Basis für die beiden Klassen HashSet und TreeSet. Es überschreibt auch keine Methoden der Oberklasse AbstractCollection, sondern fügt nur die Methode equals(Object) und hashCode() hinzu.
AbstractMap
Implementiert die Schnittstelle Map. Um eine konkrete Unterklasse zu erstellen, muss put() sinnvoll implementiert werden; ohne Überschriebenes put() folgt eine UnsupportedOperationException. Für get(Object) gibt es eine Standard-Implementierung.
Das Wissen um diese Basisimplementierung ist nützlich, wenn eigene Datenstrukturen implementiert werden. Das passiert selten, findet man aber etwa bei Google Guava.