2010-04-15 7 views
241

Angenommen, ich erstelle ein Objekt und füge es zu meinem ArrayList hinzu. Wenn ich dann ein anderes Objekt mit genau der gleichen Konstruktoreingabe erstelle, wertet die Methode die beiden Objekte als gleich aus? Angenommen, der Konstruktor macht mit der Eingabe nichts Lustiges, und die in beiden Objekten gespeicherten Variablen sind identisch. Wie bewertet die Methode contains() einer ArrayList Objekte?

ArrayList<Thing> basket = new ArrayList<Thing>(); 
Thing thing = new Thing(100); 
basket.add(thing); 
Thing another = new Thing(100); 
basket.contains(another); // true or false? 

class Thing { 
    public int value; 

    public Thing (int x) { 
     value = x; 
    } 

    equals (Thing x) { 
     if (x.value == value) return true; 
     return false; 
    } 
} 

Ist dies, wie die class sollte Rückkehr true haben umgesetzt werden?

Antwort

278

ArrayList implements die List-Schnittstelle.

Wenn Sie sich die Javadoc for List unter der contains Methode ansehen, werden Sie sehen, dass es die equals() Methode verwendet, um zu bewerten, ob zwei Objekte gleich sind.

+55

Falls Sie planen, equals() zu überschreiben, stellen Sie sicher, dass Sie auch die Methode hashcode() außer Kraft setzen. Wenn Sie nicht möchten, funktionieren die Dinge möglicherweise nicht wie erwartet, wenn Sie Sammlungen verwenden. –

+30

Dies ist eine korrekte Antwort, aber beachte, dass du deine equals-Methode ändern musst, um ein "Objekt" anstelle einer "Sache" zu akzeptieren. Wenn Sie dies nicht tun, wird Ihre equals-Methode nicht verwendet. :) – mdierker

+0

Nur für mich selbst entdeckt, dass Eclipse "Generate HashCode() und Equals" im Menü Quelle hat. –

13

Die ArrayList verwendet die in der Klasse implementierte equals-Methode (Ihre Thing-Klasse), um den Vergleich der Gleichheit durchzuführen.

+0

thx. viel appreciated! –

6

Es verwendet die equals-Methode für die Objekte. Wenn also Thing die Gleichheit nicht überschreibt und die in den Objekten gespeicherten Variablen zum Vergleich verwendet, gibt es bei der Methode nicht den Wert true zurück.

4

Andere Poster haben sich mit der Frage beschäftigt, wie contains() funktioniert.

Ein ebenso wichtiger Aspekt Ihrer Frage ist, wie man equals() richtig implementiert. Und die Antwort darauf hängt wirklich davon ab, was die Objektgleichheit für diese bestimmte Klasse ausmacht. In dem von Ihnen bereitgestellten Beispiel, wenn Sie zwei verschiedene Objekte haben, die beide x = 5 haben, sind sie gleich? Es hängt wirklich davon ab, was Sie versuchen zu tun.

Wenn Sie nur an Objektgleichheit interessiert sind, dann verwendet die Standard Implementierung von .equals() (die von Object bereitgestellten) nur Identität (d. H. This == other). Wenn das ist, was Sie wollen, dann implementieren Sie nicht gleich() für Ihre Klasse (lassen Sie es von Object erben). Der Code, den Sie geschrieben haben, ist zwar korrekt, wenn Sie nach Identität suchen, würde aber nie in einer echten Klasse erscheinen. B/c bietet keinen Vorteil gegenüber der Verwendung der standardmäßigen Object.equals() - Implementierung.

Wenn Sie gerade mit diesen Sachen beginnen, empfehle ich dringend das effektive Java-Buch von Joshua Bloch. Es ist eine großartige Lese-, und deckt diese Art von Sache (und wie man equals(), wenn Sie versuchen mehr als identitätsbasierte Vergleiche)

+0

Für meinen Zweck habe ich versucht zu sehen, ob ein Objekt von gleichem Wert in der ArrayList war. Ich nehme an, es ist eine Art Hack. Danke für die Buchempfehlung –

10

hashCode() jedes Mal, wenn Sie überschreiben equals(), auch wenn nur für den Leistungsschub. HashCode() entscheidet, in welchen "Bucket" Ihr Objekt beim Vergleich einsortiert wird, so dass alle zwei Objekte, die equal() als wahr auswerten, denselben hashCodevalue() zurückgeben sollen. Ich kann mich nicht erinnern, das Standardverhalten von hashCode() (wenn es 0 zurückgibt, dann sollte Ihr Code aber langsam funktionieren, aber wenn es die Adresse zurückgibt, wird Ihr Code fehlschlagen). Ich erinnere mich an einige Male, als mein Code fehlschlug, weil ich vergaß, hashCode() zu überschreiben.:)

5
class Thing { 
    public int value; 

    public Thing (int x) { 
     value = x; 
    } 

    equals (Thing x) { 
     if (x.value == value) return true; 
     return false; 
    } 
} 

müssen Sie schreiben:

class Thing { 
    public int value; 

    public Thing (int x) { 
     value = x; 
    } 

    public boolean equals (Object o) { 
    Thing x = (Thing) o; 
     if (x.value == value) return true; 
     return false; 
    } 
} 

Jetzt funktioniert es;)

+6

du solltest nicht Thing x = (Thing) o; ohne zuerst zu prüfen, ob das andere Objekt null ist – steelshark

47

Ich denke, dass richtige Implementierungen

public class Thing 
{ 
    public int value; 

    public Thing (int x) 
    { 
     this.value = x; 
    } 

    @Override 
    public boolean equals(Object object) 
    { 
     boolean sameSame = false; 

     if (object != null && object instanceof Thing) 
     { 
      sameSame = this.value == ((Thing) object).value; 
     } 

     return sameSame; 
    } 
} 
+7

wo ist die Implementierung der 'hashcode' Methode? – Stephan

+10

Ja, du hast Recht @Alex! Fühlen Sie sich frei, es hinzuzufügen;) – ChristopheCVB

+1

'if' Aussage ist unnötig. 'instanceof' ist genug. – Paul

5

Ich wollte nur sein sollte, dass die folgenden beachten Implementierung ist falsch, wenn value kein primitiver Typ ist:

public class Thing 
{ 
    public Object value; 

    public Thing (Object x) 
    { 
     this.value = x; 
    } 

    @Override 
    public boolean equals(Object object) 
    { 
     boolean sameSame = false; 

     if (object != null && object instanceof Thing) 
     { 
      sameSame = this.value == ((Thing) object).value; 
     } 

     return sameSame; 
    } 
} 

In diesem Fall schlage ich folgendes:

public class Thing { 
    public Object value; 

    public Thing (Object x) { 
     value = x; 
    } 

    @Override 
    public boolean equals(Object object) { 

     if (object != null && object instanceof Thing) { 
      Thing thing = (Thing) object; 
      if (value == null) { 
       return (thing.value == null); 
      } 
      else { 
       return value.equals(thing.value); 
      } 
     } 

     return false; 
    } 
} 
+0

wie dies zu implementieren, während das Duplikat zu beseitigen? – Sujay

2

Verknüpfung von JavaDoc:

booleanenthält (Object o)

Gibt true zurück, wenn diese Liste der enthält spezifiziertes Element formal, mehr gibt true zurück, wenn und nur wenn diese Liste enthält mindestens ein Element e so dass (o == null e == null: o.equals (e))

Verwandte Themen