# Eindeutige ID für Objekte als Keys in TreeMap



## JanHH (9. Apr 2009)

Hallo,

ich will Objekte mit einer TreeMap mappen. Dabei wird einem Objekt von KlasseA jeweils ein Objekt von KlasseB zugewiesen. Damit das funktioniert, muss KlasseA bekanntlich das Interface Comparable implementieren. Die Instanzen von KlasseA sind allerdings nun nicht inhaltlich sinnvoll vergleichbar, daher muss irgendwas künstliches her, was möglichst wenig Aufwand macht. Also einfach irgndetwas eindeutiges, vergleichbares, was ein Objekt so besitzt. Jedr Instanz von KlasseA eine künstliche, eindeutige ID mitzugeben, ist mir eigentlich zu aufwändig.

Was kann man denn da sonst noch machen?

Erste Idee: Speicheradresse nehmen. Ich habe allerdings bisher keine Funktion "getMemoryAdress" oder so etwas gefunden

Hashcode. Ist sicherlich praktikabel, da der HashCode eines Objektes *in der Regel* der Speicheradresse entspricht, und *in der gegenwärtigen Implementierung* aus praktikablen Gründe zwei verschiedene Objekte auch immer zwei verschiedene Hashcodes bekommen. Würde also funktionieren, ist aber nicht sicher, weil die erwähnten Vorraussetzungen nicht zugesichert sind.

Ansonsten bleibt wohl nur, selber irgendeine Lösung bauen. Könnte mir z.B. einen Applikationsweiten UniqueRandomGenerator vorstellen, der Zufallszahlen erzeugt, die sich nicht wiederholen. Aber das ist mir eigentlich zu aufwändig, wenn es auch eine einfachere Lösung gibt.

Fürs erste werde ich mal die Hashcode-Variante probieren..

Jemand eine Idee?

Gruß+Danke
Jan


----------



## SlaterB (9. Apr 2009)

was ist denn daran aufwendig? die Ids müssen nicht mal zufällig sein, ein long-Wert 1.. unendlich reicht

statische Variable, die bei 1 anfängt, Zugriff nur über synchronisierte Methode, das könnte in eine separate Generator-Klasse,

in den Objektklassen brauchst du sowieo ein Attribut + vielleicht ein getter, um die id zu speichern, also

private long id;
public long getId() {
if (id == 0) {
  id = Generator.createId(); // bei Bedarf hier wie dort synchronized
}
return id;
}


edit:
> und *in der gegenwärtigen Implementierung* aus praktikablen Gründe zwei verschiedene Objekte auch immer zwei verschiedene Hashcodes bekommen.

kann man nur Integer.Max_VALUE viele Objekte erstellen?
ok, vom Arbeitsspeicher her bestimmt nicht so gut zu testen 
aber spätestens wenn man die Objekte mit Id in eine Datei schreibt..

irgendwann ist natürlich immer Schluss, auch bei long, dann gehts mit String/ BigInteger weiter


----------



## bygones (9. Apr 2009)

JanHH hat gesagt.:


> Hashcode. Ist sicherlich praktikabel, da der HashCode eines Objektes *in der Regel* der Speicheradresse entspricht


definitiv eine Argument auf das ich mich *NIE* verlassen würde....


----------



## 0x7F800000 (9. Apr 2009)

"Die Instanzen von KlasseA sind allerdings nun nicht inhaltlich sinnvoll vergleichbar"
...aber du willst dennoch aus irgendeinem Grund eine TreeMap einsetzen.
Knick in der Logik...? :autsch:


----------



## FArt (9. Apr 2009)

1. Hier kriegt man einfach eine ID her: UUID (Java 2 Platform SE 5.0)
2. Was meinst du mit "zuweisen" und wozu dann "Comparable"?
3. Der Hashcode entspricht der Speicheradresse? Was ist denn das für ein Käse. Der Hashcode ist ein Hash über den relevanten Inhalt einer Objektinstanz und nicht eindeutig.
4. Wenn die Objekte nicht sinnvoll vergleichbar sind, warum steckst du sie dann in eine sortierte Datenstrutkur?


----------



## JanHH (9. Apr 2009)

Das mit hash-Code=Speicheraddresse habe ich irgendwo gelesen. Die online-java-Doku selber sagt, dass praktikablerweise zwei verschiedene Objekte in der Regel auch verschiedene hash-Codes haben.

Die Frage nach dem "warum".. ich habe halt Paare von Objekten, die zueinander in Bezug stehen. Ich bekomme irgendwoher Objekt A, und brauche das "dazugehörige" Objekt B. Allerdings sind diese Objekte inhaltlich sonst in keiner Weise miteinander verwandt, es ist nicht sinnvoll, das eine als Member des anderen zu organisieren.

Naja und zum mappen derartiger Dinge gibt es ja die Maps in java, nicht wahr . Ob die sortiert sind oder nicht, ist ja egal.. es geht eher um schnellen Zugriff.

Aber vielleicht stellt einfach das verwenden einer HashMap die Lösung dar? Diese ist ja nicht "natürlich sortiert", und wenn ich das richtig sehe, braucht man da keine Comparable-Objekte?

Ansonsten ist die Lösung mit dem "Generator", also einem Applikationsweiten, statischen Zähler, vermutlich die Beste. Bin da mittlerweile auch drauf gekommen.

Danke für die Antworten.


----------



## 0x7F800000 (9. Apr 2009)

JanHH hat gesagt.:


> Die Frage nach dem "warum".. ich habe halt Paare von Objekten, die zueinander in Bezug stehen. Ich bekomme irgendwoher Objekt A, und brauche das "dazugehörige" Objekt B. Allerdings sind diese Objekte inhaltlich sonst in keiner Weise miteinander verwandt, es ist nicht sinnvoll, das eine als Member des anderen zu organisieren.
> 
> Naja und zum mappen derartiger Dinge gibt es ja die Maps in java, nicht wahr .


ja, genau.



> Ob die sortiert sind oder nicht, ist ja egal..


nein, ist es nicht.


> es geht eher um schnellen Zugriff.


Dann brauchst du natürlich HashMap mit O(1) statt SortedMap mit O(lg(n))



> Aber vielleicht stellt einfach das verwenden einer HashMap die Lösung dar?


sieht ganz danach aus.


> Diese ist ja nicht "natürlich sortiert"


Nein. und die reihenfolge in der man das einfügt spielt auch keine rolle, da wird alles durcheinandergeworfen. 


> und wenn ich das richtig sehe, braucht man da keine Comparable-Objekte?


dort muss man aber vorsichtig und mit bedacht die equals-methode und die hashCode-methode implementieren, sodass sie den vorgeschriebenen vertrag erfüllen:
"a equals b => hash(a)==hash(b)"



> Ansonsten ist die Lösung mit dem "Generator", also einem Applikationsweiten, statischen Zähler, vermutlich die Beste. Bin da mittlerweile auch drauf gekommen.


Wenn es so ist, dann brauchst du wohl nichtmal die equals bzw hashCode zu überschreiben. Dann testest du nur noch auf ==. Da musst du dir aber wirklich sicher sein, dass alle objekte "inhaltliche unikate" sind (was imho selten brauchbar ist... ???:L)


----------



## JanHH (10. Apr 2009)

Also SO wichtig ist Geschwindigkeit nun auch nicht.. ich muss die im Grunde nur irgendwie einander Zuordnen können. Im Grunde könnte ich es auch komplett selber programmieren.. dau eine Klasse "TwoObjects", die zwei Objekte aufnimmt, und eine Liste solcher Objekte, und damit dann die Zuordnungen realisieren. Da muss dann halt zum wiederfinden jeweils die ganze Liste komplett durchsucht werden, das könnte im allerschlimmsten realen Anwendungsfall zu 100 Mal durchsuchen einer Liste mit 100 Einträgen führen. Aber sogar das wäre wohl noch brauchbar. Aber Tree oder HashMap sind da natürlich effizienter.

Elegant war bei Smalltalk die Dictionary-Klasse, wo man einfach beliebige Objekte als Keys für beliebige andere Objekte verwenden konnte.. aber dem kommt die HashMap wohl relativ nahe.


----------



## SlaterB (10. Apr 2009)

solange jedes Objekt unique ist und du wirklich mit denselben Objekt A suchst statt einem gleichen Objekt A,
geht die ganz normale HashMap ohne überschriebene equals/ hashCode-Methode (in A)

wenn du jetzt schon überlegtest, in A eine Id hinzuzufügen, 
kannst du dann nicht auch gleich setB() getB() einbauen?


----------



## Gelöschtes Mitglied 5909 (10. Apr 2009)

[highlight=java]
public class SequenceGenerator {

    private AtomicLong atomicLong = new AtomicLong(0);

    public long getId() {
        return atomicLong.incrementAndGet();
    }

}
[/highlight]


----------



## JanHH (11. Apr 2009)

Das Atomic-Dings, danke für den Hinweis, kommt mir ehrlich gesagt etwas albern vor.. so, als wolle sun in den java-Bibliothkenen wirklich alles abnehmen und jede noch so banale Funktionalität schon vorgefertigt bereitstellen.

Mein Programm hat zwei Einsatzzwecke.. für einen von beiden würde B als Member von A gut funktionieren (in der Tat war es bis vor kurzem auch ziemlich genau so), bei dem anderen gibt es keine Objekte vom Typ B, die gesamte Mapping-Sache fällt weg, und der Einsatzzweck ist auch noch deutlich speicherkritischer. Daher besser nicht so eine Lösung (ausserdem brauche ich das ab und an auch umgekehrt, A als Member von B, und das geht gar nicht, weil es sich bei B um Swing-Komponenten handelt, wo ich nicht so ohne weiteres member hinzufügen kann/will).

Naja. Aber mit der HashMap läufts ja nun auch scheinbar ganz gut.

Danke
Jan


----------



## 0x7F800000 (11. Apr 2009)

JanHH hat gesagt.:


> Das Atomic-Dings, danke für den Hinweis, kommt mir ehrlich gesagt etwas albern vor.. so, als wolle sun in den java-Bibliothkenen wirklich alles abnehmen und jede noch so banale Funktionalität schon vorgefertigt bereitstellen.


sowas zu synchronisieren ist weniger banal, sondern eher nervig... :noe:
Dass da überall "atomic atomic atomic" dabei steht ist dir bestimmt aufgefallen, oder hast du nur auf diese komische methode geachtet?


----------



## JanHH (11. Apr 2009)

Ich versteh die Frage grad nicht so ganz.. aber mein eigentliches Problem habe ich gelöst (durch simples verwenden von HashMaps).

Danke
Jan


----------

