Objekt verändert sich abhängig von anderen

Hallo Community,

ich hab da ein seltsames Problem.

Zur vorgeschichte ich lese eine xml aus und speichere mir das Ergebnis in eine ArrayList diese als Paremeter ein Objekt von einer von mir selbsterstellten Klasse hat. -> ArrayList Diese Liste habe ich zwei mal, einmal die Originale, die zur Laufzeit unverändert bleibt und einmal die “further” Liste, die dann ausgegeben wird, sprich diese Liste ändert die Values zur Laufzeit.

Nun soll es so sein das aus dieser ArrayList die IDs in einer Liste gezeigt werden und wenn der Benutzer einen Listeneintrag selektiert ihm dann die passenden Values angezeigt werden. Unter den Textfeld wo der Value aus der XML angezeigt wird kann der Benutzer einen neuen Value dafür eingeben.

Wenn ich nun aber einen neuen Wert eingebe wird der auch dann oben (Wert aus xml) angezeigt obwohl dort ja der alte Wert stehen sollte.

Vorher hatte ich anstatt meine Klasse, einen String verwendet, da war dann auch das Verhalten wie erwartet doch seit dem ich die Custome Klasse hab geht das nicht mehr.
Meine Vermutung war dann demnach die ganze Sache Immutable zu machen, das hat aber auch nicht geklappt.

Hat jemand eine Idee?

Gruß
Mad

Beispielcode könnte hilfreich sein.

Zunächst hört sich:

ArrayList Diese Liste habe ich** zwei mal**, einmal die Originale, die zur Laufzeit unverändert bleibt und einmal die “further” Liste

verlockend an.

Wie erstellst du diese zweite Liste?

nicht ganz verstanden, aber du redest von 2 listen. Sicher dass die beiden Listen nicht einfach auf die selben Objekte zeigen ? ergo wenn du eines aenderst wird auch automatisch die andere liste geaendert ?

Heißt der Wert wird zurück in das Objekt “geschrieben”? Die zwei Listen nutzen Dir dann nichts, wenn Du in beiden Listen die selben Objekte hast. Du müsstest in der zweiten Liste eine echte Kopie der Original Objekte halten. Evlt. gibt es da auch eine bessere Lösung bei der Du eine Liste mit den Originalwerten hast und zusätzlich nur die tatsächlich geänderten Objekte hälst. Für Empfehlungen müsste man den konkreten Anwendungsfall kennen.

Entschuldigt da war ich wieder zu vertieft das ich das wichtigste vergessen habe.

[QUOTE=Sunshine]Beispielcode könnte hilfreich sein.

Zunächst hört sich:

verlockend an.

Wie erstellst du diese zweite Liste?[/QUOTE]

Ich hatte es einmal auf die weiße mit den Immutable gemacht. Da sah es wie folgt aus:


for (HouseStringData houStringData : listOriginalModel) {
                            listOriginalModelPrep.put(houStringData.getId(),
                                    houStringData);
listPreparModel.put(houStringDataPrep.getId(),
                                    houStringDataPrep);

                        }

kurz und knapp da war alles in einer Schleife, das andere war dann das ich das Objekt listOriginalModel kopiert bze “geclont” habe und dann einmal über das Original und dann über die Kopie von dem Original, was wie folgt aussahe:


for (HouseStringData houStringData : listOriginalModel) {
                            listOriginalModelPrep.put(houStringData.getId(),
                                    houStringData);
                        }
                       
                        ArrayList<HouseStringData> listprep = (ArrayList<HouseStringData>) listOriginalModel.clone();
                       
                        for (HouseStringData houStringDataPrep : listprep) {
                            listPreparModel.put(houStringDataPrep.getId(),
                                    houStringDataPrep);
                        }

ja, genau das war/ist auch meine Vermutung, deswegen das Immutable und zum anderen die Kopie/Clone von der Liste.

Also Anwendungsfall wäre wenn dann so das alle Werte mit in die neue xml geschrieben werden. Auch wo der Benutzer nichts eingetragen hat.

es IST das problem : du hast nur einmal deine objekte aber zwei listen die darauf verweisen
da nützt ein List.clone() überhaupt nichts weil du so nur die liste selbst clonest, nicht aber ihren inhalt

ergo : es gibt kein zweites objekt das auf änderungen des ersten “mit-reagiert” da du nur ein objekt hast

lösung : deep-clone
du musst in deiner custom-klasse clone() so sinnvoll implementieren das ein NEUES objekt geliefert wird welches auch nur NEUE objekte enthält, also eine echt tiefen-kopie

so bald du auch nur an einer stelle “neueReferenz=alteReferenz” stehen hast ist dein clone() unvollständig da wieder irgendwo auf ein und das selbe objekt referenziert wird anstatt ein völlig neues zu erzeugen

Ganz klar:
in beiden Listen liegen die selben Objekte.
Liste1 ----> Objekt <---- Liste2

Es gibt 2 Möglichkeiten:[ol]
[li]die schlechte: erzeuge in der Schleife, in der Du die Objekte in die zweite Liste legt neue.
[/li][li]die bessere erzeuge ein zweites Feld in den Daten-Objekten eines für den alten Wert und eines für den neuen.
[/li][/ol]

bye
TT

Danke an euch beiden.

Werde dann wohl variante 2 nehmen, scheint mir eleganter und etwas performance “freudiger”

Gruß

[QUOTE=Timothy_Truckle;29315]
Es gibt 2 Möglichkeiten:[ol]
[li]die schlechte: erzeuge in der Schleife, in der Du die Objekte in die zweite Liste legt neue.
[/li][li]die bessere erzeuge ein zweites Feld in den Daten-Objekten eines für den alten Wert und eines für den neuen.
[/li][/ol][/QUOTE]

Ist die zweite Möglichkeit tatsächlich die bevorzugte?
Wenn nun mehrere Felder in dieser Klasse geändert werden können ( dem entsprechend für jedes Feld zwei Attribute ), wirkt das irgendwie redundant, falls es nie zu einer Änderung kommen sollte.

Ich denke ich würde in dem Fall einen Copy-Konstruktor verwenden und mit einer zweiten Liste arbeiten.

[QUOTE=Sunshine]Ich denke ich würde in dem Fall einen Copy-Konstruktor verwenden und mit einer zweiten Liste arbeiten.[/QUOTE]Und diese kopierten Objekte sind dann nicht redundant?

bye
TT

[QUOTE=Timothy_Truckle;29348]Und diese kopierten Objekte sind dann nicht redundant?

bye
TT[/QUOTE]

Wenn ich erst kopiere, wenn ich etwas verändern möchte, nein.

[QUOTE=Sunshine]Wenn ich erst kopiere, wenn ich etwas verändern möchte, nein.[/QUOTE]Das kann ich aber auch innerhalb des Objektes erreichen, dazu muss ich nicht das komplette Objekt kopieren:```class DataObjekt{
privat final String property1old;
privat String property1;

public DataObjekt(String property1){
property1old= property1;
this.property1=property1; // beide Referenzen zeigen auf das selbe String-Objekt -> keine Redundanz (der Daten)
}
public void setProperty1(String property1){
this.property1=property1;
}
}```Das schöne an dieser Lösung ist, dass ich außerhalb der Klasse DataObjekt keine Rücksicht auf die Dualität der Werte nehmen muss (ausgenommen die Anzeige des alten Wertes…).

bye
TT

So hatte ich es ja auch gemacht, wenn ich mir den String aus den Objekt geholt habe, hatte ich in der Methode ein “return new String(property)” zurück gegeben, trotzdem wurde anscheinend noch auf das gleiche String gezeigt.

Ich hab es nun so wie es vorgeschlagen wurde gemacht, in den DataObjekt ein zusätzliches Attribut angelegt was dann halt “furtherValue” heißt, dadurch ensteht mir in den Sinne keine Redundanz, wenn der Benutzer nichts eingibt wird dieses Feld auch nicht gefüllt.

PS: Während ich das nun geschrieben habe, ist mir etwas aufgefallen. Kann es sein das ich zwars jedes mal ein neues String Objekt erzeugt habe, aber dadurch das ich von den DataObjekt kein neues erzeugt habe sich deshalb die Werte immer syncron verhalten haben?

Und für was sollte der neue String gut sein? String ist ohnehin immutable und kann nicht maniupuliert werden.

Lies dir das Problem durch dann wirst du sehen das ich genau das Problem hatte … aus der Not heraus macht man manchmal unmögliche/sinnfreie Sachen

[QUOTE=Madlip]So hatte ich es ja auch gemacht, wenn ich mir den String aus den Objekt geholt habe, hatte ich in der Methode ein “return new String(property)” zurück gegeben, trotzdem wurde anscheinend noch auf das gleiche String gezeigt.[/QUOTE]Ja.

[QUOTE=Madlip;29610]Ich hab es nun so wie es vorgeschlagen wurde gemacht, in den DataObjekt ein zusätzliches Attribut angelegt was dann halt “furtherValue” heißt, dadurch ensteht mir in den Sinne keine Redundanz, wenn der Benutzer nichts eingibt wird dieses Feld auch nicht gefüllt.[/QUOTE]Dann hast Du wahrscheinlich einige if(null==furtherValue){...}else{...}im Code oder?
Mit meinem Vorschlag aus Antwort #12 brauchst Du diese if gar nicht.

P[QUOTE=Madlip;29610]S: Während ich das nun geschrieben habe, ist mir etwas aufgefallen. Kann es sein das ich zwars jedes mal ein neues String Objekt erzeugt habe, aber dadurch das ich von den DataObjekt kein neues erzeugt habe sich deshalb die Werte immer syncron verhalten haben?[/QUOTE]Ja.

bye
TT

Danke werd ich noch ergänzen.

Man ruft nie, nie, nie new String(...), ausser man weiss ganz genau, was man da macht.