Frage zu Hastabelle bzw. interne Datenhaltung

Hallo,

ich hätte eine Frage zur programminteren Verwaltung von Daten.

Ich stelle in einen Java-Gui (Applet) Formulare da. Die Info welches Feld wo im Formular liegt erhalte ich durch ein Servlet. Das Applet kennt nur den Names eines Feldes und die entspr. Swing-Komponente.
Das Servlet weiß was passiert,wenn z.B. eine ComboBox angeklickt wird.

Die Felder des Formulars speichere ich mir in einer Hashtabele. Key ist der Feldname und Value ist eine Referenz auf die Swing-Komponente.

Somit kann ich jederzeit über den Feldnamen auf die Swing-Komponente zugreifen und z.B. ihren aktuellen Wert abfragen oder setzen.

Soll das Formular gespeichert werden übergebe ich dem Servlet die aktuelle Belegung aller Formularfelder. Wie die Daten dann gespeichert werden ist Sache des Servlets.

Nun kommt meine Frage:
Damit ich die aktuelle Belegung der Formularfelder erhalte mach ich folgendes:
Aus der Hashtabelle (fields) hole ich mir mit fields.key() die Schlüsselfelder als Enumeration (keys). Dann hole ich mir über eine While-Schleife den key als String
„varName = (String) keys.nextElement();“
Über varName kann ich dann wieder die Hashtabelle lese und mir die SwingKomponente holen „comp = (JComponent)fields.get(varName);“
Von der Komponete kann ich mir nun den aktuellen Wert geben lassen
z.B: „value = comp.getText;“

Feldname und Wert werden nun in eine neue Hashtabelle gespeichert und dem Servlet übergeben.

Ist die Verwaltung der Daten so sinnvoll oder wie macht man das besser ? Es ist doch irgendwie blöd erst den Key zu lesen damit man dann mit dem Key auf die eigentlichen Daten zugreifen kann.

In obigem Fall könnte man ja auch direkt auf fields.values() zugreifen und dann über die Komponente den Namen des Feldes erfragen.
An anderen Stellen im Programm habe ich aber ein ähnliched Problem.
In einem TabbedPane können mehrere Formulare liegen d.h. unter jedem Reiter ein eigenes Formular. Während der Anzeige des Formulars weiß ich, dass auf meinem Hauptfprmular ein TabbedPane sitze. Die Namen und Anzahl der Reiter ergibt sich wiederum aus einer Hashtabelle. Key ist der Name des Reiters, Value ist eine Liste (LinkedList) der auf diesem Reiter anzuzeigenden Formularfelder. Um an die Daten zu kommen muß ich auch wieder die Key der Hashtabelle lesen um dann auf die Liste der Formularfelder zugreifen zu können. Hier kann man den Namen des Tabs nicht aus der Feldliste bestimmen d.h. hier muß ich den Key lesen damit ich den Namen des Tabs kenne.

Was wäre hier eine bessere Lösung ?

Danke
Albert

Hi,

vielleicht hilft es etwas wenn Du Dir eine eigene Liste erstellst, die einen Namen haben kann. Also:

public class MyList
extends LinkedList
{
private String name;

}

Somit kannst Du jeder Liste einen eindeutigen Namen geben. Wenn Du dann über die Listeinträge läufts kannst Du auch immer den Namen der Liste auslesen. D.h. der Name des Reites = Name der Liste

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Mein Problem ist auch, dass ich häufig Key Value Beziehungen habe und dass beim Verarbeiten die Reihenfolge wichtig ist. Also der erste Wert den ich in eine Hashtabelle schreibe muß eigentlich auch wieder der erste Wert sein, den ich verarbeite. Lese ich die Keys als Enumeration aus und verarbeite sie, dann ist die Reihenfolge nicht mehr richtig.

Albert

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Mein Problem ist auch, dass ich häufig Key Value
Beziehungen habe und dass beim Verarbeiten die Reihenfolge
wichtig ist. Also der erste Wert den ich in eine Hashtabelle
schreibe muß eigentlich auch wieder der erste Wert sein, den
ich verarbeite. Lese ich die Keys als Enumeration aus und
verarbeite sie, dann ist die Reihenfolge nicht mehr richtig.

Albert

Hi,

um dies zu erreichen, solltest du dir die Keys beim Einfügen zusätzlich in einer ArrayList speichern. Smoit kannst du Reihenfolge-abhängig durch Iteration über die Liste den zugehörigen Wert aus deiner HashTable lesen.

Ciao, Bill

Hi,

ich würde hierzu erstmal folgendes Interface implementieren:

interface FormComponent
{
 public void setValue();
 public Object getValue();
 public String getFieldName();
 public JComponent getSwingComponent();
}

Dann kannst du zum Beispiel folgende Klasse erstellen:

public class StringFormComponent implements FormComponent
{
 private JTextField m\_TextField;
 ...
 public JComponent getSwingComponent()
 {
 return m\_TextField;
 }
 ...
}

Über entsprechendes EventHandling könntest du intern gleich das Ändern eines Wertes an das gehaltene Value-Objekt weitergeben.

Die richtige Component könntest du dir über eine Factory erzeugen lassen.

public class MyFormComponentFactory
{
 private static Map m\_Registry = new HashMap();
 ...
 static
 {
 m\_Registry.put(String.class, StringFormComponent.class);
 ...
 }

 public static FormComponent createComponent(String fieldName, Object value)
 {
 // 1. die Class des value als Schlüssel für die Registry verwenden 
 // 2. per Reflection das geeignete Component erzeugen
 ...
 return createdComponent;
 }
}

Die einzelnen Formular-Elemente speicherst du dann in einer Map und die dazugehörigen Schlüssel gleichzeitig in einer ArrayList:

...
 private Map m\_FormComponents;
 private List m\_FormComponentKeys;
 ...
 public void fill()
 {
 ... 
 FormComponent comp;
 // Daten vom Servlet lesen
 // Iteration Anfang
 comp = MyFormComponentFactory.createComponent(fieldName, value);
 m\_FormComponents.put(comp.getFieldName(), comp);
 m\_FormComponentKeys.add(comp.getFieldName());
 // Iteration Ende
 }

Du erreichst somit, dass du jederzeit über die Liste auf die geordnete Sammlung der Feldnamen zugreifen kannst. Gleichzeitig kannst du durch iterieren und Weitergabe des Schlüssels die Map durchlaufen und einmal das Formular mit deinen Swing-Komponenten füllen, das andere Mal deine Map zum Speichern für das Servlet füllen (durch Abfrage mittels getValue()).

In meinen Augen ist dies ein sinnvolle Kapselung der Daten.

Für jedes Tab deines Formulars könntest du noch eine geeignete Klasse rundumstülpen, die dir 1 bis Tabs verwaltet, die intern so funktionieren, wie oben beschrieben.

Übrigens:
Nutze LinkedList mit großer Vorsicht und nur dann, wenn sie von Nöten ist (siehe Doku). LinkedList ist sehr performancehungrig und in den meisten Fällen ist eine ArrayList wesentlich besser (sowohl vom Speicherplatz her, als auch von den Zugriffszeiten). Ich konnte erst letztens eine Funktionalität mit DB-Abfragen von 12 Minuten Dauer auf 5 Sekunden (!) optimieren, indem ich die fälschlicherweise von meinem Vorprogrammierer verwendete LinkedList durch eine ArrayList ersetzt habe.

Ciao, Bill