Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage
<< | < | > | >> | API | Kapitel 14 - Collections I

## 14.4 Die Klasse Hashtable

- 14.4 Die Klasse Hashtable
  - 14.4.1 Einfügen von Elementen
  - 14.4.2 Zugriff auf Elemente
  - 14.4.3 Hashtable als Iterator
  - 14.4.4 Die Klasse Properties

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. |  |
Hinweis

### 14.4.1 Einfügen von Elementen

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`.

### 14.4.2 Zugriff auf Elemente

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.

### 14.4.3 Hashtable als Iterator

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

Listing 14.3: Anwendung der Klasse Hashtable

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

### 14.4.4 Die Klasse Properties

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. |  |
JDK1.1-1.4

|  | 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. |  |
Hinweis

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
<< | < | > | >> | API | © 1998-2002 Guido Krüger, http://www.javabuch.de