Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage |
<< | < | > | >> | API | Kapitel 14 - Collections I |
Die Klasse Hashtable ist eine Konkretisierung der abstrakten Klasse Dictionary. Diese stellt einen assoziativen Speicher dar, der Schlüssel auf Werte abbildet und über den Schlüsselbegriff einen effizienten Zugriff auf den Wert ermöglicht. Ein Dictionary speichert also immer zusammengehörige Paare von Daten, bei denen der Schlüssel als Name des zugehörigen Wertes angesehen werden kann. Über den Schlüssel kann später der Wert leicht wiedergefunden werden.
Da ein Dictionary auf unterschiedliche Weise implementiert werden kann, haben die Java-Designer entschieden, dessen abstrakte Eigenschaften in einer Basisklasse zusammenzufassen. Die Implementierung Hashtable benutzt das Verfahren der Schlüsseltransformation, also die Verwendung einer Transformationsfunktion (auch Hash-Funktion genannt), zur Abbildung von Schlüsseln auf Indexpositionen eines Arrays. Weitere Konkretisierungen der Klasse Dictionary, etwa auf der Basis binärer Bäume, gibt es in Java derzeit nicht.
Neben den erwähnten abstrakten Eigenschaften besitzt Hashtable noch die konkreten Merkmale Kapazität und Ladefaktor. Die Kapazität gibt die Anzahl der Elemente an, die insgesamt untergebracht werden können. Der Ladefaktor zeigt dagegen an, bei welchem Füllungsgrad die Hash-Tabelle vergrößert werden muß. Das Vergrößern erfolgt automatisch, wenn die Anzahl der Elemente innerhalb der Tabelle größer ist als das Produkt aus Kapazität und Ladefaktor. Seit dem JDK 1.2 darf der Ladefaktor auch größer als 1 sein. In diesem Fall wird die Hashtable also erst dann vergrößert, wenn der Füllungsgrad größer als 100 % ist und bereits ein Teil der Elemente in den Überlaufbereichen untergebracht wurde.
Wichtig bei der Verwendung der Dictionary-Klassen ist, daß das Einfügen und der Zugriff auf Schlüssel nicht auf der Basis des Operators ==, sondern mit Hilfe der Methode equals erfolgt. Schlüssel müssen daher lediglich inhaltlich gleich sein, um als identisch angesehen zu werden. Eine Referenzgleichheit ist dagegen nicht erforderlich. |
|
Eine Instanz der Klasse Hashtable kann mit Hilfe eines parameterlosen Konstruktors angelegt werden:
public Hashtable() |
java.util.Hashtable |
Das Einfügen von Elementen erfolgt durch Aufruf der Methode put:
public Object put(Object key, Object value) |
java.util.Hashtable |
Dieser Aufruf fügt das Schlüssel-Werte-Paar (key, value) in die Hashtable ein. Weder key noch value dürfen dabei null sein. Falls bereits ein Wertepaar mit dem Schlüssel key enthalten ist, wird der bisherige Wert gegen den neuen ausgetauscht, und put liefert in diesem Fall den Wert zurück, der bisher dem Schlüssel zugeordnet war. Falls der Schlüssel bisher noch nicht vorhanden ist, ist der Rückgabewert null.
Der Zugriff auf ein Element erfolgt mit Hilfe der Methode get über den ihm zugeordneten Schlüssel. get erwartet ein Schlüsselobjekt und liefert den dazu passenden Wert. Falls der angegebene Schlüssel nicht enthalten war, ist der Rückgabewert null:
public Object get(Object key) |
java.util.Hashtable |
Zusätzlich zu den bisher erwähnten Methoden gibt es noch zwei weitere mit den Namen contains und containsKey. Sie überprüfen, ob ein bestimmter Wert bzw. ein bestimmter Schlüssel in der Hashtable enthalten ist:
public boolean contains(Object value) public boolean containsKey(Object key) |
java.util.Hashtable |
Der Rückgabewert ist true, falls das gesuchte Element enthalten ist, andernfalls ist er false. Bei der Verwendung dieser Funktionen ist zu beachten, daß die Suche nach einem Wert wahrscheinlich viel ineffizienter ist als die Suche nach einem Schlüssel. Während der Schlüssel über die Transformationsfunktion sehr schnell gefunden wird, erfordert die Suche nach einem Wert einen sequentiellen Durchlauf durch die Tabelle.
In der Klasse Hashtable gibt es zwei Iteratoren, die zur Auflistung von Schlüsseln und Werten verwendet werden können:
public Enumeration elements() public Enumeration keys() |
java.util.Hashtable |
Die Methode elements liefert einen Iterator für die Auflistung aller Werte in der Hashtable. In welcher Reihenfolge die Elemente dabei durchlaufen werden, ist nicht definiert. Da eine Hash-Funktion die Eigenschaft hat, Schlüssel gleichmäßig über den verfügbaren Speicher zu verteilen, ist davon auszugehen, daß die Iteratoren ihre Rückgabewerte in einer zufälligen Reihenfolge liefern.
Analog zu elements liefert keys eine Auflistung aller Schlüssel, die sich in der Hash-Tabelle befinden. Wie üblich liefern beide Methoden ein Objekt, welches das Interface Enumeration implementiert. Wie zuvor erklärt, erfolgt der Zugriff daher mit Hilfe der Methoden hasMoreElements und nextElement.
Das folgende Beispiel verdeutlicht die Anwendung einer Hashtable:
001 /* Listing1403.java */ 002 003 import java.util.*; 004 005 public class Listing1403 006 { 007 public static void main(String[] args) 008 { 009 Hashtable h = new Hashtable(); 010 011 //Pflege der Aliase 012 h.put("Fritz","f.mueller@test.de"); 013 h.put("Franz","fk@b-blabla.com"); 014 h.put("Paula","user0125@mail.uofm.edu"); 015 h.put("Lissa","lb3@gateway.fhdto.northsurf.dk"); 016 017 //Ausgabe 018 Enumeration e = h.keys(); 019 while (e.hasMoreElements()) { 020 String alias = (String)e.nextElement(); 021 System.out.println( 022 alias + " --> " + h.get(alias) 023 ); 024 } 025 } 026 } |
Listing1403.java |
Das Programm legt eine leere Hashtable
an, die zur Aufnahme von Mail-Aliasen verwendet werden soll. Dazu
soll zu jeder E-Mail-Adresse ein kurzer Aliasname gepflegt werden,
unter dem die lange Adresse später angesprochen werden kann.
Das Programm legt zunächst die Aliase »Fritz«, »Franz«,
»Paula« und »Lissa« an und assoziiert jeden mit
der zugehörigen E-Mail-Adresse. Anschließend durchläuft
es alle Schlüssel und gibt zu jedem den dazu passenden Wert aus.
Die Ausgabe des Programms ist:
Lissa --> lb3@gateway.fhdto.northsurf.dk
Paula --> user0125@mail.uofm.edu
Franz --> fk@b-blabla.com
Fritz --> f.mueller@test.de
Die Klasse Properties ist aus Hashtable abgeleitet und repräsentiert ein auf String-Paare spezialisiertes Dictionary, das es erlaubt, seinen Inhalt auf einen externen Datenträger zu speichern oder von dort zu laden. Ein solches Objekt wird auch als Property-Liste (oder Eigenschaften-Liste) bezeichnet. Zur Instanzierung stehen zwei Konstruktoren zur Verfügung:
public Properties() public Properties(Properties defaults) |
java.util.Properties |
Der erste legt eine leere Property-Liste an, der zweite füllt sie mit den übergebenen Default-Werten. Der Zugriff auf die einzelnen Elemente erfolgt mit den Methoden getProperty und propertyNames:
public String getProperty(String key) public String getProperty(String key, String defaultValue) public Enumeration propertyNames() |
java.util.Properties |
Die erste Variante von getProperty liefert die Eigenschaft mit der Bezeichnung key. Ist sie nicht vorhanden, wird null zurückgegeben. Die zweite Variante hat dieselbe Aufgabe, gibt aber den Standardwert defaultValue zurück, wenn die gesuchte Eigenschaft nicht gefunden wurde. Mit propertyNames kann ein Enumeration-Objekt beschafft werden, mit dem alle Eigenschaften der Property-Liste aufgezählt werden können.
Zum Speichern einer Property-Liste steht die Methode store zur Verfügung:
public void store(OutputStream out, String header) throws IOException |
java.util.Properties |
Sie erwartet einen OutputStream als Ausgabegerät (siehe Kapitel 19) und einen Header-String, der als Kommentar in die Ausgabedatei geschrieben wird.
Das Gegenstück zu store ist load. Mit ihr kann eine Property-Datei eingelesen werden:
public void load(InputStream in) throws IOException |
java.util.Properties |
Hier muß ein InputStream übergeben werden (siehe ebenfalls Kapitel 19), der die Daten der Property-Liste zur Verfügung stellt.
Im JDK 1.1 wurde statt der Methode store die Methode save zum Speichern einer Property-Liste verwendet. Diese hatte dieselbe Signatur, löste aber bei I/O-Problemen keine IOException aus. Mit dem JDK 1.2 wurde save als deprecated deklariert und durch store ersetzt. |
|
Property-Dateien sind Textdateien mit einem recht einfachen Aufbau. Je Zeile enthalten sie einen Schlüssel und den zugehörigen Wert. Beide sind durch ein Gleichheitszeichen voneinander getrennt. Falls das erste nicht-leere Zeichen einer Zeile ein "#" oder "!" ist, wird die gesamte Zeile als Kommentar angesehen und beim Einlesen ignoriert. Zusätzlich sind einige Escape-Zeichen wie \t, \n, \r, \\, \" oder \' erlaubt, und es gibt die Möglichkeit, sehr lange Schlüssel-Wert-Paare auf mehrere Zeilen zu verteilen. Weitere Details können in der API-Dokumentation der Methoden load und store nachgelesen werden. |
|
Wir wollen an dieser Stelle die Betrachtung der Klasse Properties abschließen. Ein weiteres Beispiel zu ihrer Verwendung findet sich in Abschnitt 16.3.1.
Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage, Addison Wesley, Version 3.0.1 |
<< | < | > | >> | API | © 1998-2003 Guido Krüger, http://www.javabuch.de |