Hi Leute!
Ich versuche gerade ein Programm zu schreiben, mit dem man Datenbestände aus einer Excel-Datei laden, und dann verschiedene Spalten miteinander vergleichen kann. Ich habe bereits eine Klasse erstellt, die eine Zeile aus der Excel-Tabelle repräsentiert. Genannt habe ich sie ganz allgemein "Record", und die sieht so aus:
Ein Record ist also ein Datensatz, der intern durch eine Liste definiert wird, und in den nur String verstaut werden dürfen. Wenn eine Null-Referenz eingefügt wird, dann wird anstatt dieser ein Leerstring eingefügt. Mit der Klasse und der JExcel API ist es auch kein Problem, Daten aus einer Excel-Tabelle in viele unterschiedliche "Records" zu packen.
Jetzt möchte ich mir eine Datenstruktur basteln, in der ich diese Records verstauen kann. Dort gibt es aber mehrere Sachen, die beachtet werden sollen: Die Datenstruktur hat eine bestimmte Dimension, und soll auch nur Records aufnehmen können, die die gleiche größe wie die Dimension der Datenstruktur besitzt. Desweiteren sollen die Datensätze eindeutig sein. D.h. beim Einfügen will ich überprüfen, ob es bereits einen Record gibt, der an einer bestimmten, vorher definierten Position, bereits diesen Wert hat. AUs diesem Grund habe ich mir überlegt, das ganze irgendwie über eine Hashtable zu realisieren. Ich definiere also vorher, an welcher Position des Records mein "Key-Wert" steht, und füge den Wert von diesem dann als Schlüssel, und den Records an sich dann als Objekt des Hashtable-Objektes ein. Doppelt vorkommene Datensätze sollen dann beide in einer seperaten Liste landen, sodass ich diese dann für spätere vergleiche aussortieren kann. Ich habe mir dann ungefähr folgendes überlegt
Also ungefähr so:
Jetzt stelle ich mir die Frage, ob das nicht irgendwie eleganter wäre, evtl. die Klasse der Hashtable zu erweitern, da ich dann so z.B. auch direkt über diesen RecordContainer iterieren könnte und auch die andere Funktionalität zur Verfügung hätte. Kann da jemand was zu sagen, wie ich das ganze nun besser realisiere? Ich möchte hinterher dann zwei RecordContainer haben, welche letztendlich ja dann die Zeilen meiner ursprünglichen Excel-Dateien beinhalten, und dann einzelne Spalten miteinander vergleichen, d.h., ob ein Record aus dem ersten Container mit dem Key xy auch einen Record in im zweiten Container besitzt, und ob der Inhalt an einer bestimmten stelle gleich ist.
Ich hoffe, dass man meinem Gefasel ansatzweise folgen kann *g*
Ich versuche gerade ein Programm zu schreiben, mit dem man Datenbestände aus einer Excel-Datei laden, und dann verschiedene Spalten miteinander vergleichen kann. Ich habe bereits eine Klasse erstellt, die eine Zeile aus der Excel-Tabelle repräsentiert. Genannt habe ich sie ganz allgemein "Record", und die sieht so aus:
Code:
package comparator.core;
import java.util.ArrayList;
import java.util.List;
/**
* Eine Speichereinheit zum halten von Informationen im Stringformat
*
* @author Danny
* @version 0.3
*/
public class Record {
/**
* Liste zum speichern der einzelnen String-Werte
*/
private List<String> data;
/**
* Erzeugt einen leeren Record
*/
public Record() {
this.data = new ArrayList<String>();
}
/**
* Erstellt einen leeren Record mit einer Initial-Kapazität
* @param capacity
*/
public Record(int capacity) {
if (capacity < 0) {
throw new IllegalArgumentException("Kapazität muss >= 0 sein!");
}
this.data = new ArrayList<String>(capacity);
}
/**
* Erzeugt einen neuen Record anhand eines übergebenen String-Arrays
* Dieser Konstruktor erzeugt einen neuen Record, indem zuerst eine
* neue Liste mit der Kapazität der Länge des Arrays erzeugt, und
* anschließend über das Array iteriert und alle Werte einzeln in die
* Liste einfügt
* @param values Inhalt des Records
*/
public Record(String[] values) {
this(values.length);
for (String s : values) {
checkAndAdd(s);
}
}
/**
* Fügt einen String-Wert in den Record ein
* Der hinzuzufügende Wert wird an die Private Methode
* <code>checkAndAdd()</code> übergeben und dort hinzugefügt.
* @param value
*/
public void addValue(String value) {
checkAndAdd(value);
}
/**
* Gibt den String-Wert des Records an der gewünschten Stelle zurück
* @param position die Stelle des gewünschten String-Wertes
* @throws IndexOutOfBoundsException
* @return der String-Wert von <code>position</code>
*/
public String getValueAt(int position) {
if (position < 0 || position >= this.data.size()) {
throw new IndexOutOfBoundsException("Kein Wert an dieser Position");
}
return this.data.get(position);
}
/**
* Setzt den String-Wert des Records an der gewünschten Stelle
* Wenn der String einer Null-Referenz entspricht, dann wird an stelle
* dieser ein Leerstring eingefügt
* @param position die Position des zu ändernden Wertes
* @param value der neue Wert
*/
public void setValueAt(int position, String value) {
if (position < 0 || position >= this.data.size()) {
throw new IndexOutOfBoundsException("Kein Wert an dieser Position");
}
if (value == null) {
value = "";
}
this.data.set(position, value);
}
/**
* Löscht den Wert an einer bestimmten Position
* @throws IndexOutOfBoundsException
* @param position
*/
public void removeValueAt(int position) {
if (position < 0 || position >= this.data.size()) {
throw new IndexOutOfBoundsException("Kein Wert an dieser Position");
}
}
/**
* Gibt die Größe des Records zurück
* @return die Größe des Records
*/
public int size() {
return this.data.size();
}
/**
* Erweitert einen Record mit Leerstrings bis zu einer bestimmten Größe
* @param size die gewünschte Größe
*/
public void expandSizeWithEmptyStrings(int size) {
while (this.data.size() < size) {
this.data.add("");
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("comparator.core.Record[");
for (String s : this.data) {
sb.append(s + ";");
}
sb.append("]");
return sb.toString();
}
/**
* Überprüft den String und fügt ihn in die Liste ein
* Falls der übergebene String eine Null-Referenz ist, so wird an
* Stelle dieser ein Leerstring eingefügt.
* @param value
*/
private void checkAndAdd(String value) {
if (value == null) {
this.data.add("");
} else {
this.data.add(value);
}
}
}
Jetzt möchte ich mir eine Datenstruktur basteln, in der ich diese Records verstauen kann. Dort gibt es aber mehrere Sachen, die beachtet werden sollen: Die Datenstruktur hat eine bestimmte Dimension, und soll auch nur Records aufnehmen können, die die gleiche größe wie die Dimension der Datenstruktur besitzt. Desweiteren sollen die Datensätze eindeutig sein. D.h. beim Einfügen will ich überprüfen, ob es bereits einen Record gibt, der an einer bestimmten, vorher definierten Position, bereits diesen Wert hat. AUs diesem Grund habe ich mir überlegt, das ganze irgendwie über eine Hashtable zu realisieren. Ich definiere also vorher, an welcher Position des Records mein "Key-Wert" steht, und füge den Wert von diesem dann als Schlüssel, und den Records an sich dann als Objekt des Hashtable-Objektes ein. Doppelt vorkommene Datensätze sollen dann beide in einer seperaten Liste landen, sodass ich diese dann für spätere vergleiche aussortieren kann. Ich habe mir dann ungefähr folgendes überlegt
Also ungefähr so:
Code:
package comparator.core;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
/**
*
* @author Danny
* @version 0.1
*/
public class RecordContainer {
/**
* Hashmap zum speichern aller gültigen Records
*/
private Hashtable<String, Record> records;
/**
* Die Liste für die doppelten Records
*/
private List<Record> duplicates;
/**
* Die Dimension des RecordContainers
*/
private int dimension;
/**
* Erstellt einen neuen RecordContainer mit der gewünschten Dimension
* @param dimension die Dimension des Containers
*/
public RecordContainer(int dimension) {
setDimension(dimension);
this.duplicates = new ArrayList<Record>();
this.records = new Hashtable<String, Record>();
}
/**
* Gibt die Dimension des RecordContainers zurück
* @return die Dimension des RecordContainers
*/
public int getDimension() {
return this.dimension;
}
/**
* Fügt einen Record in den RecordContainer ein
*
* Die Methode überprüft zunächst, ob der Record in den Container eingefügt
* werden kann, d.h. ob die Größe auch der Dimension des Containers entspricht.
* Falls es bereits einen Record mit dem angegebenen Key in dem
* Container gibt, dann werden beide Records in die Liste mit den
* Dublikaten gespeichert.
*
* @throws IllegalArgumentException falls die Größe des Records nicht der
* Dimension des RecordContainers entspricht
*
* @param record der hinzuzufügende Record
*/
public void addRecord(String key, Record record) {
// Größe des Records muss der Dimension der RecordList entsprechen
if (record.size() != this.dimension) {
throw new IllegalArgumentException("Record hat die falsche Dimension");
}
// Wenn es einen Record mit diesem Key bereits in der Hashtable
// gibt, dann beide Records in die Dubletten-Liste einfügen
if (this.records.containsKey(key)) {
this.duplicates.add(this.records.get(key));
this.records.remove(key);
this.duplicates.add(record);
} else {
this.records.put(key, record);
}
}
/**
* Gibt den Record mit einem bestimmten Key zurück
* @param key der Key des Records
* @return den gewünschten Record
*/
public Record getRecord(String key) {
return this.records.get(key);
}
/**
* Löscht den Record mit dem angegebenen Key
* @param key der Key des Records
*/
public void removeRecord(String key) {
this.records.remove(key);
}
/**
* Gibt zurück, ob der RecordContainer einen Record mit dem Key key beinhaltet
* @param key der Key des Records
* @return <code>true</code> fall ein Record mit dem Key key existiert
*/
public boolean containsKey(String key) {
return this.records.containsKey(key);
}
/**
* Setzt die Dimension des RecordContainers
* Der Container kann nur Records mit der größe aufnehmen, deren Größe
* der Dimension dieses RecordContainers entsprechen.
* @param dimension die Dimension des RecordContainers
*/
private void setDimension(int dimension) {
if (dimension < 0) {
throw new IllegalArgumentException("Dimension muss größer 0 sein");
}
this.dimension = dimension;
}
}
Jetzt stelle ich mir die Frage, ob das nicht irgendwie eleganter wäre, evtl. die Klasse der Hashtable zu erweitern, da ich dann so z.B. auch direkt über diesen RecordContainer iterieren könnte und auch die andere Funktionalität zur Verfügung hätte. Kann da jemand was zu sagen, wie ich das ganze nun besser realisiere? Ich möchte hinterher dann zwei RecordContainer haben, welche letztendlich ja dann die Zeilen meiner ursprünglichen Excel-Dateien beinhalten, und dann einzelne Spalten miteinander vergleichen, d.h., ob ein Record aus dem ersten Container mit dem Key xy auch einen Record in im zweiten Container besitzt, und ob der Inhalt an einer bestimmten stelle gleich ist.
Ich hoffe, dass man meinem Gefasel ansatzweise folgen kann *g*