Die beste Art zu verwenden enthält in einer ArrayList in Java?

8

Ich habe eine ArrayList in Java, die aus einem Typ besteht, der zwei Strings und eine ganze Zahl enthält. Ich kann erfolgreich testen, ob ein Element dieser ArrayList gleich einem anderen ist, aber ich finde, dass die contains-Methode fehlschlägt. Ich glaube, das liegt an der Tatsache, dass mein Typ nicht primitiv ist.

Nun sehe ich zwei Alternativen dazu und ich frage mich, welche die beste Option ist:

  1. Um meine eigene contains-Methode zu implementieren, indem ich durch die ArrayList iteriere und die Gleichheit jedes Elements mit dem, nach dem ich suche, überprüfe und dann die Schleife aufbringe.

  2. Oder eine HashMap meines Typs als Schlüssel mit einer Ganzzahl als Wert anstelle der ArrayList zu verwenden. Hier kann ich mit der Methode containsKey prüfen, ob in der HashMap bereits ein Element existiert.

Der einzige Nachteil gegenüber Ansatz 2 ist, dass der Wert in meinem Fall weitgehend überflüssig ist.

    
Pesto 12.06.2009, 14:27
quelle

5 Antworten

24

Wahrscheinlich haben Sie einfach vergessen, equals() und hashCode() in Ihrem Typ zu überschreiben. equals() ist das, nach dem contains() sucht.

Aus dem Javadoc :

  

Gibt true zurück, wenn diese Liste das angegebene Element enthält. Formal ausgedrückt, wird true zurückgegeben, wenn und nur wenn diese Liste mindestens ein Element e enthält, so dass (o==null ? e==null : o.equals(e)) .

Seit der Standardimplementierung von equals testet auf Referenzgleichheit, es ist nicht geeignet für benutzerdefinierte Datentypen wie dieser.

(Und wenn Sie equals und hashCode nicht überschrieben haben, wäre die Verwendung Ihrer Typen als Schlüssel in einem HashMap ebenso sinnlos.)

Bearbeiten: Beachten Sie, dass Sie zum Überschreiben die exakte Signatur angeben müssen.

%Vor%

Dies ist ein sehr starkes Argument für die Verwendung der @Override Anmerkung; Das erste Beispiel wäre zur Kompilierzeit fehlgeschlagen, wenn es mit @Override annotiert wurde.

    
Michael Myers 12.06.2009 14:29
quelle
14

Meine Vermutung ist, dass Sie nur eine "stark typisierte" equals-Methode geschrieben haben, anstatt gleich (Object) zu überschreiben. Mit anderen Worten, wenn Sie haben:

%Vor%

brauchst du

%Vor%

auch zum Überschreiben von Object.equals.

Das passt zu "equals funktioniert, aber enthält nicht, weil Ihre Tests wahrscheinlich die stark typisierten equals aufrufen, aber ArrayList nicht.

    
Jon Skeet 12.06.2009 14:34
quelle
3

Haben Sie die equals-Methode überschrieben? Dies ist erforderlich, damit contains korrekt funktioniert.

    
amarillion 12.06.2009 14:29
quelle
2

Denken Sie daran, dass zwei Objekte Ihres Typs nur dann gleich sind, wenn sie die gleiche Instanz des Objekts sind, wenn Sie die Methode equals () nicht überschreiben. Die ArrayList-Klasse verwendet diese Methode, um zu überprüfen, ob sie das angegebene Objekt enthält. Außerdem müssen Sie die Signatur exakt anpassen, was bedeutet, dass ein Objekt als Parameter und kein Foo verwendet werden muss.

Außerdem schreibt der Objektvertrag vor, dass Sie hashCode () überschreiben müssen, wenn Sie equals () überschreiben. Wenn Sie dies nicht tun, wird eine HashMap oder HashSet Ihre zwei Objekte nicht als gleich identifizieren, selbst wenn die ArrayList dies tut (HashMap prüft auf identische Hashes und ruft dann equals () auf, um nach tatsächlicher Gleichheit zu suchen). Wenn ArrayList also sagt, dass zwei Elemente nicht gleich sind, gibt es auch keine Möglichkeit, dass HashMap dies tut. Dies bedeutet, dass Ihre zweite Lösung nicht funktioniert.

Meine Empfehlung ist zu überprüfen, dass Sie equals () und hashCode () richtig überschreiben und dass ihre Signaturen denen in der Object-Klasse entsprechen.

    
James 12.06.2009 14:42
quelle
0

vielleicht stattdessen die Integer-Klasse? dann können Sie einen Objektvergleich durchführen

    
Rickster 12.06.2009 14:30
quelle

Tags und Links