Mal was allgemeines zu equals()

  • Themenstarter Themenstarter Spacerat
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
S

Spacerat

Gast
Also, ich hatte mal folendes ausprobiert als ich mir einen Cache für Bilder (bzw. Texturen) basteln wollte.

Code:
Vector<BufferedImage> cache = new Vector<BufferedImage>();
BufferedImage img1 = new BufferedImage(10, 10, BufferedImage.TRANSLUCENT);
BufferedImage img2 = new BufferedImage(10, 10, BufferedImage.TRANSLUCENT);
if(!img1.equals(img2)) cache.add(img2);

Nun die grosse Preisfrage: Was glaubt ihr was passiert nach der "equals();"-Methode. Landet es im Vector "cache" oder nicht?

Ok. Das kann ich schon mal beantworten. Es landet im Cache! Allerdings völlig zu unrecht, da img1 hier ein Element von einem existierenden Cache simulieren soll, welches mit einem anderen verglichen werden soll. Man sieht aber deutlich, das beide Bilder "equal" sind. Warum wird also false zurückgegeben?

Huch, selbst dafür hab' ich noch 'ne Antwort auf Lager. Und zwar folgende: BufferedImage, sowie dessen Interfaces und Vaterklassen implementieren allesammt die Methode "equals()" nicht. Daher wird "Object.equals()" verwendet, welche wie folgt aussieht.

Code:
public boolean Object equals(Object obj)
{
    return this==obj;
}

Aha! Und nu? Hier wird eindeutig der inhaltliche Vergleich in einen Objekt-Vergleich umgewandelt, was aber noch nicht allzu schlimm ist, da es an dieser Stelle die beste Möglichkeit darstellt. Wenn man nun noch die Klassen ausserhalb von "java.lang" unter die Lupe nimmt, fällt einem auf, das die wenigsten davon eine "equals()"-Methode besitzen. Deshalb kommt jetzt mal die rein rhetorische Frage, welche eigentlich an SUN gehen müsste:

Welchen Sinn macht "equals()" wenn es nicht vernünftig implementiert wird?

cu Spacerat

P.S.: Ich erwarte natürlich keine direkte Antwort darauf, allerdings wären einige Stellungnahmen angebracht. Zuletzt habe ich meinen Cache doch noch hinbekommen. BufferedImage extended und bei "equals()" die beiden in zwei "int[]"-Arrays gelesen und deren Werte verglichen.
 
Zuletzt habe ich meinen Cache doch noch hinbekommen. BufferedImage extended und bei "equals()" die beiden in zwei "int[]"-Arrays gelesen und deren Werte verglichen.
Nach oben
Voilà. Also was soll das blöde rumgestänker :bae: :wink:
 
Welchen Sinn macht "equals()" wenn es nicht vernünftig implementiert wird?
Denk nochmal drüber nach, bevor du dich hier aus dem Fenster lehnst

Kennst du den Kontrakt für equals? Was sollte denn passieren wenn du das Bild in eine Image castest und dann mit einem VolatileImage vergleichst??

Man sieht aber deutlich, das beide Bilder "equal" sind.
völliger Unsinn: du siehst das rein zufällig in deinem Spezialfall, weil der Vergleich sofort nach dem Konstruktor erfolgt, im allgemeinen sind da 3 zillionen Codezeilen dazwischen....

wie sollte denn equals für ein java.awt.Image deiner Meinung nach funktionieren? mit anderen Worten: welche Semantik schwebt dir vor??

man kann nicht einfach die bytes nehmen, das würde die "lazy loaded" Klassen völlig unsinnig machen usw. usf.
 
Denk dran, wenn du die equals-Methode überschreibst, auch die hashCode-methode zu überschreiben.
Wenn x.equals(z), dann sollte auch x.hashCode() == z.hashCode() sein.
 
Zu weit aus dem Fenster lehnen?

1. Welche Bedeutung hat laut Java-Spezifikation eine equals()-Methode? RICHTIG! Prüfung auf inhaltliche Gleichheit! Und was ich hier angeprangert habe, ist, das das nicht immer gegeben ist, da das überschreiben dieser Methode immer gerne "vergessen" wird. Der Hashcode ist dabei völlig uninteressant. Wichtig ist, das die INHALTE (bei BufferedImage wohl die Pixel) verglichen werden. deswegen...

2. Wenn ich ein und die selbe Datei in zwei BufferedImage-Instanzen lade (Toolkit.createImage("dateiname")), sollte man stets zwei Instanzen erhalten, welche unbedingt inhaltlich gleich sein sollten! Das bedeutet:

img1 == img2 = false
img1.equals(img2) = true

3. Ich finde, das ist etwas über was ihr mal nachdenken solltet.

cu Spacerat
 
Mal davon abgesehen das du ein Jahr zu spät bist:
Das ist totaler Blödsinn, weil jeder selbst entscheidet was er als equals betrachtet.
Bei Images macht sowas beispielsweise überhaupt keinen Sinn (nach welchen Maßstäben sollte das auch verglichen werden).
Der Hashcode ist dabei völlig uninteressant.
Ist auch Schwachfug weil man equals nicht überschreiben soll ohne auch Hashcode zu überschreiben.
 
nach welchen Maßstäben sollte das auch verglichen werden

...Pixel für Pixel für Pixel...

cu Spacerat

P.S.: zu spät? Kann sein... Forste gerade meine Beiträge nach längst vergessenen Threads durch...
 
Spacerat hat gesagt.:
...Pixel für Pixel für Pixel...
Ja.... das wird furchtbar performant in jeder Collection Implementierung.
Warum haben die Leute von SUN da nicht dran gedacht... :roll:

Denk doch mal drüber nach, selbst wenn das Performance Problem nicht wäre, was ist mit dem Lazy load von Images?
Was ist mit den unterschiedlichen Colormodels?
Sind 2 Bilder gleich wenn sie die gleichen Pixel haben auch wenn das eine Colormodel Transparenz unterstützt und das andere nicht?
Wenn das eine ein TrueColor fähiges Colormodel hat aber nur aus Schwarz/Weiß Pixeln besteht die denen eines anderen Images mit S/W Colormodel entsprechen?
Das ist schlicht Unsinn...
 
Ach was solls... Ich mach' da mal 'nen Haken dran...

cu Spacerat
 
Wildcard hat gesagt.:
Der Hashcode ist dabei völlig uninteressant.
Ist auch Schwachfug weil man equals nicht überschreiben soll ohne auch Hashcode zu überschreiben.
Zu sagen, das ist Schwachfug, ist Schwachfug :bae:

Die Regel ist ganz klar:

Wenn zwei Objekte "equals" sind, MÜSSEN sie den gleichen hashCode haben.
Wenn zwei Objekte NICHT "equals" sind, KÖNNEN sie den gleichen hashCode haben, sollten es aber nicht.

Code:
public boolean equals(Object other)
{
    return false;
}
Ich überschreib' garnix :wink:
 
Marco13 hat gesagt.:
Wenn zwei Objekte "equals" sind, MÜSSEN sie den gleichen hashCode haben.
Wenn zwei Objekte NICHT "equals" sind, KÖNNEN sie den gleichen hashCode haben, sollten es aber nicht.
Ich hab auch überlegt das so zu schreiben, die sache ist allerdings die:
Sie MÜSSEN nicht.
Man verletzt den Contract und bringt diverse Klassen wie zum Beispiel die Hashmap aus dem Tritt.
Wenn man allerdings auf die Konsequenzen pfeift kann man equals auch alleine überschreiben.
Aber deine Formulierung verdeutlicht das Problem besser :wink:
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben