In che modo il metodo contains () di ArrayList valuta gli oggetti?

Diciamo che creo un object e lo aggiungo al mio ArrayList . Se poi creo un altro object con esattamente lo stesso input del costruttore, il metodo contains() valuterà i due oggetti per essere lo stesso? Supponiamo che il costruttore non faccia nulla di divertente con l’input e che le variabili memorizzate in entrambi gli oggetti siano identiche.

 ArrayList basket = new ArrayList(); 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; } } 

È così che dovrebbe essere implementata la class affinché abbia contains() restituisca true ?

ArrayList implements l’interfaccia elenco.

Se osservate Javadoc per List nel metodo contains , vedrete che usa il metodo equals() per valutare se due oggetti sono uguali.

Penso che dovrebbero essere le giuste implementazioni

 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; } } 

ArrayList usa il metodo equals implementato nella class (il tuo caso Thing class) per fare il confronto degli uguali.

Generalmente si dovrebbe anche eseguire l’override di hashCode() ogni volta che si esegue l’override di equals() , anche se solo per l’aumento delle prestazioni. HashCode() decide su quale “bucket” viene ordinato il tuo object quando fa un confronto, quindi qualsiasi due oggetti che equal() restituisce true dovrebbe restituire lo stesso value() hashCode value() . Non riesco a ricordare il comportamento predefinito di hashCode() (se restituisce 0 allora il tuo codice dovrebbe funzionare ma lentamente, ma se restituisce l’indirizzo, il tuo codice fallirà). Ricordo un sacco di volte in cui il mio codice è fallito perché ho dimenticato di sovrascrivere hashCode() . 🙂

Usa il metodo di uguale sugli oggetti. Pertanto, a meno che Thing non esegua l’override e utilizzi le variabili memorizzate negli oggetti per il confronto, non restituirà true nel metodo contains() .

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

Devi scrivere:

 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; } } 

Ora funziona 😉

Volevo solo sottolineare che la seguente implementazione è errata quando il value non è un tipo primitivo:

 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 tal caso, propongo il seguente:

 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; } } 

Altri poster hanno affrontato la domanda su come contains () funziona.

Un aspetto altrettanto importante della tua domanda è come implementare correttamente equals (). E la risposta a questo è realmente dipendente da ciò che costituisce l’uguaglianza oggettuale per questa particolare class. Nell’esempio che hai fornito, se hai due oggetti diversi che hanno entrambi x = 5, sono uguali? Dipende davvero da cosa stai cercando di fare.

Se ti interessa solo l’uguaglianza degli oggetti, l’implementazione predefinita di .equals () (quella fornita da Object) utilizza solo l’id quadro (ovvero questo == altro). Se questo è quello che vuoi, allora non implementare equals () sulla tua class (lascialo ereditare da Object). Il codice che hai scritto, sebbene sia corretto se stai andando per id quadro, non apparirebbe mai in una vera class b / c, non offre alcun vantaggio sull’uso dell’implementazione Object.equals () predefinita.

Se hai appena iniziato con questa roba, ti consiglio vivamente il libro Effective Java di Joshua Bloch. È una buona lettura, e copre questo genere di cose (oltre a come implementare correttamente equals () quando si sta tentando di fare qualcosa di più dei confronti basati sull’id quadro)

Collegamento da JavaDoc :

contiene boolean (object o)

Restituisce vero se questa lista contiene l’elemento specificato. Più formalmente, restituisce true se e solo se questo elenco contiene almeno un elemento e tale che (o == null? E == null: o.equals (e))