Perché AbstractCollection non implementa equals ()?
-
19-08-2019 - |
Domanda
Lo sapevi che:
Map<Object,Object> m1 = new HashMap<Object, Object>();
Map<Object,Object> m2 = new HashMap<Object, Object>();
System.out.println("m1.equals(m2) = "+m1.equals(m2));
System.out.println("m1.keySet().equals(m2.keySet()) = "
+m1.keySet().equals(m2.keySet()));
System.out.println("m1.entrySet().equals(m2.entrySet()) = "
+m1.entrySet().equals(m2.entrySet()));
System.out.println("m1.values().equals(m2.values()) = "
+m1.values().equals(m2.values()));
avrebbe prodotto:
m1.equals(m2) = true
m1.keySet().equals(m2.keySet()) = true
m1.entrySet().equals(m2.entrySet()) = true
m1.values().equals(m2.values()) = false
Ciò è causato dal fatto che AbstractCollection
(che HashMap $ Values ??
eredita da) non ignora #equals ()
.
Hai idea del perché sia ??così?
Soluzione
Secondo il contratto di Collection # equals ()
, non esistono metodi equals generici () per Collection
e quindi AbstractCollection impossibile fornirne uno.
Nota che HashMap $ Values ??
non è né un Set né un Elenco, quindi il dilemma e in un certo senso il motivo per cui non supporta equals ()
.
Altri suggerimenti
Sia AbstractList che AbstractSet estendono AbstractCollection e hanno comportamenti diversi per i loro metodi equals (), specificati dalle interfacce Elenco e Set . L'interfaccia per Collezione dice:
Mentre l'interfaccia Collection aggiunge no clausole del contratto generale per Object.equals, programmatori who implementare l'interfaccia Collection & Quot; direttamente " (in altre parole, crea un classe che è una raccolta ma non lo è un set o un elenco) devono prestare attenzione se scelgono di ignorare il Object.equalsQ.
Quindi AbstractCollection non dovrebbe assolutamente sovrascrivere equals (). Detto questo, non so davvero perché HashMap $ Values ??non implementerebbe equals () stesso.
Non sono sicuro se questo sia il motivo ufficiale, ma AbstractCollection evita di aggiungere vincoli semantici su potenziali sottoclassi. La semantica dell'uguaglianza è determinata dalla natura della struttura di dati ereditaria concreta, e in particolare in base al fatto che la propria struttura sia ordinata e se consenta duplicati.
Ad esempio, considera TreeSet, LinkedList, Bag, ecc.
A proposito, in relazione al codice che hai pubblicato, qual è il tipo effettivo di ciò che viene restituito dai valori? Dovrebbe essere una sottoclasse con un'implementazione concreta. Se la tua mappa è vuota quando esegui questo codice, è possibile che tu finisca con qualcosa che non considera uguali due insiemi vuoti.