|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Bannato
Iscritto dal: Feb 2003
Città: Anche Chuck Norris usa Debian e Gnome
Messaggi: 1270
|
[JAVA] String e equals
Perche equals serve a confrontare due stringhe quando esiste compareTo? Forse perchè le stringhe sono oggetti immutabili e hanno preferito sfruttare anche il metodo equals per effettuare il confronto altrimenti non avrebbe avuto senso?
|
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
Quote:
compareTo è un operatore di ordinamento, equals è un operatore di uguaglianza, puoi usare quello che vuoi, però è più comodo scrivere string1.equals(string2) piuttosto che string1.compareTo(string2) == 0 inoltre tu potresti voler ridefinire l'operatore equals, ma tenere compareTo immutato |
|
|
|
|
|
|
#3 | |
|
Bannato
Iscritto dal: Feb 2003
Città: Anche Chuck Norris usa Debian e Gnome
Messaggi: 1270
|
Quote:
|
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
in realta' non vedo perche' l'essere immutabili influisca sull'uso del metodo equals... equals e compareTo li ho sempre visti in coppia (per ogni classe che implementa un ordinamento tra le sue istanze) e il motivo e' quello che ti ho scritto nella prima risposta.
Ultima modifica di mad_hhatter : 13-12-2007 alle 00:50. |
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Innanzitutto equals() è definito nella classe Object. Ogni sottoclasse di Object quindi ha la possibilità di fare l'override di equals() per definire in modo più corretto come stabilire se due oggetti sono "meaningfully equivalent" (di significato equivalente). E se si fa l'override di equals() si dovrebbe anche fare l'override di hashCode(). I due metodi sono legati tra di loro da un "contratto" ben preciso. Se si implementa equals() ma non hashCode() tale contratto non verrebbe più rispettato. compareTo() invece ha un obiettivo diverso ed è legato all'interfaccia Comparable. Mai notato che se una classe ha il compareTo(), è anche Comparable?? Comparable e il metodo compareTo() servono tipicamente per determinare un ordine tra due oggetti. L'ordine fornito da un Comparable viene chiamato il "natural ordering" (ordinamento naturale). Ma è anche possibile definire N altri ordinamenti specifici implementando l'interfaccia Comparator in apposite classi separate. Quindi, come vedi, equals() e compareTo() hanno obiettivi diversi. E infine, nota, la documentazione di compareTo() dice: It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)). Quindi potrebbe anche capitare che equals() e compareTo() non abbiano alcuna relazione tra di loro.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#6 | |
|
Bannato
Iscritto dal: Feb 2003
Città: Anche Chuck Norris usa Debian e Gnome
Messaggi: 1270
|
Quote:
"ABC".equals("ABC") restituisce true |
|
|
|
|
|
|
#7 | ||||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Ma in una sottoclasse che ha un qualche stato è buona norma ridefinire correttamente equals() altrimenti due oggetti diversi ma con lo stesso identico stato non verrebbero visto come "uguali". Quote:
String ha uno stato e quindi equals() viene ridefinito in modo che non si basi solamente sui reference. In più implementa Comparable e viene fatto in modo che la uguaglianza coincida per equals() e compareTo(). Come hai letto nella nota che ho riportato, è raccomandato ma non strettamente obbligatorio/richiesto. Non so dirti se nel framework ci sono delle classi che non fanno coincidere l'uguaglianza per equals() e compareTo(). Se non devi fare cose davvero particolari o "strane" è bene far coincidere l'uguaglianza. Quote:
Quote:
Tra l'altro, le due stringhe che hai usato sopra sono stringhe literal uguali. Il compilatore lo capisce e ne mette solo una nel constant-pool. Quindi quelle due stringhe hanno lo stesso identico reference. Ma ti dico di più. equals() di String innanzitutto verifica se this == oggetto_passato. Quindi nel caso particolare sopra ritorna subito true senza nemmeno vedere il contenuto delle stringhe.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||||
|
|
|
|
|
#8 | ||
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
infatti: Quote:
Cmq solitamente nelle implementazioni a 32 bit viene usato il reference per generare l'hashcode.
__________________
|
||
|
|
|
|
|
#9 | ||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Ciò che hai riportato vale per hashCode(), che è più particolare perché deve ritornare un int. Anche in questo caso, nella classe Object non è che si possa usare chissà che cosa e infatti tipicamente l'intero ritornato è basato sull'indirizzo interno dell'oggetto. E la nota spiega bene la questione. Quote:
Il metodo hashCode() in Object è marcato "native", non so esattamente cosa faccia (bisognerebbe vedere i sorgenti nativi). Su una architettura a 64 bit, se dovessi farlo io, farei in modo che hashCode() prenda l'indirizzo a 64 bit nativo e ne faccia lo XOR della parte alta e bassa per ottenere un valore a 32 bit da far ritornare. E magari funziona proprio così .... (non lo so).
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
non lo so.. se per pure sfiga ti capita la parte bassa e alta di un oggetto uguali ma scambiate hai lo stesso hashcode sinceramente non ho idea di come sia implementato e di guardarmi i sorgenyi della VM non ne ho proprio voglia dato che x oggi la mia dose quotidiana non voluta di c me la sono dovuta sorbire (maledetto linux
__________________
|
|
|
|
|
|
|
#11 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
La cosa che è veramente importante è che i valori che si possono ottenere da hashCode() siano molto ben "sparpagliati". Se poi ci sono delle collisioni, chissenefrega (più o meno...
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) Ultima modifica di andbin : 13-12-2007 alle 22:46. |
|
|
|
|
|
|
#12 | |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
Quote:
grazie mille |
|
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Se sei tu che devi implementare hashCode() è chiaro che non puoi "fregartene" delle collisioni. Devi realizzare un buon algoritmo di hash che minimizzi le collisioni. E come farlo dipende ovviamente da quanti/quali dati hai come "stato" nella tua classe.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
Quote:
ho una classe RfidTag che contiene il membro long id. Io voglio che per una Hashtable<RfidTag, Blabla> il metodo containsKey(tag) ritorni true se nella table c'è una key tag_1 avente lo stesso id di tag anche se tag e tag_1 sono oggetti distinti. Avevo ridefinito il metodo equals di RfidTag, ma poi mi sono accorto, leggendo il sorgente del metodo containsKey(), che oltre a equals viene testato anche l'hashCode. Allora ho ridefinito il metodo hashCode in RfidTag facendo lo xor della prima metà dell'id con la seconda metà... però mi viene il dubbio che questo possa avere degli effetti collaterali pur rispettando il contratto del metodo hashCode. Dove posso trovare info su buoni algoritmi di hash? grazie mille per l'aiuto PS: a che scopo dobbiamo cercare di minimizzare le collisioni? per motivi prestazionali o logico-semantici? |
|
|
|
|
|
|
#15 | ||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Non saprei dirti. Però inizia a guardare a partire da <qui>. Quote:
Un caso limite che in genere viene usato per spiegare questa questione è un hashCode() che restituisce un valore costante: Codice:
public int hashCode () {
return 123;
}
Con un valore costante in pratica ci sarebbe sempre al 100% una "collisione".
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
molte grazie andbin!
lo xor l'ho usato perché ne avevi parlato tu qualche post più su... mi fa piacere di aver azzeccato la tecnica giusta grazie infinite! |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 01:13.




















