PDA

View Full Version : [JAVA] hashset, strano comportamento


Prorad
22-03-2010, 16:13
Salve a tutti

poniamo che io abbia la classe Concetto, sulla quale ho ridefinito il metodo hashcode(). Purtroppo l'ho ridefinito male ed ho un sacco di collisioni, ma per adesso non posso farci nulla.

Poniamo anche che io abbia un metodo trovaVicini() che mi restituisce un HashSet<Concetto> e su tale set eseguo una iterazione (nota: l'ordine di visita è importante).

Poniamo anche che in tutto questo io stia utilizzando una libreria X.

Se lancio 10 volte il programma, ottengo 10 volte esattamente lo stesso risultato, quindi trovaVicini mi ha dato sempre lo stesso ordine.

Ad un certo punto cambio la libreria X per la libreria Y.

Nonostante ne X ne Y siano correlate ai Set o a Concetto, per qualche motivo che non mi spiego, noto che trovaVicini mi restituisce l'HashSet in ordine diverso rispetto al solito.
Infatti se lancio 10 volte il programma, ottengo 10 volte esattamente lo stesso risultato, quindi trovaVicini mi ha dato sempre lo stesso ordine, solo che non è più quello di prima.

Non riesco a capire se è normale e soprattutto perchè ha aspettato che cambiassi libreria per decidere di cambiare ordine.

Se qualcuno ha qualche suggerimento è ben accetto, mi rendo conto di non essere stato molto preciso ma non so neanche io come spiegarlo. Non posso postare il codice perchè richiederebbe di postare mezzo progetto o giù di li...

Thx in advance.

WarDuck
22-03-2010, 16:42
Per l'HashSet non è garantito l'ordine.

Forse viene modificato quando le classi vengono ricompilate, ma su questo non saprei dirti.

So per certo che non garantisce l'ordine per cui se hai bisogno che sia garantito usa un'altra Collection.

wizard1993
22-03-2010, 17:12
ad esempio treeset, che implementa la stessa interfaccia di set ma garantisce l'ordine

Prorad
22-03-2010, 18:06
ok, diciamo che il fatto che cambi l'ordine allo stato attuale delle cose non mi cambia granchè, però volevo essere certo del fatto che potesse essere colpa dell'hashset e soprattutto ero curioso di capirne le motivazioni.

Siccome il metodo trovaVicini si trova in una libreria, in teoria non potrei toccarlo, anche se in pratica si perchè ho i sorgenti. Potrei fare una zozzata e prendere l'hashset in uscita e schiaffarlo in un treeset+comparator da passare al resto del codice, spero solo che non mi picchi a livello prestazionale, visto che già così sono al limite :D .

thx

banryu79
22-03-2010, 18:13
Potrei fare una zozzata e prendere l'hashset in uscita e schiaffarlo in un treeset+comparator da passare al resto del codice, spero solo che non mi picchi a livello prestazionale, visto che già così sono al limite

Se non puoi creare il TreeSet fin dall'inizio e usare direttamente quello, e invece usi un HashSet di cui poi, dopo, devi ottenere una "vista ordinata", penso che ti convenga evitare di generare un TreeSet (ordina gli elementi durante l'inserimento degli stessi e ogni add ha costo log(n)) e invece generare una List (copia dell'hash set disordinato) che poi ordini con un comparator (Collection.sort usa un merge sort).

Non vorrei aver detto una fesseria, magari attendi conferme, smentite o alternative in merito da altri utenti.

Prorad
23-03-2010, 10:58
Se non puoi creare il TreeSet fin dall'inizio e usare direttamente quello, e invece usi un HashSet di cui poi, dopo, devi ottenere una "vista ordinata", penso che ti convenga evitare di generare un TreeSet (ordina gli elementi durante l'inserimento degli stessi e ogni add ha costo log(n)) e invece generare una List (copia dell'hash set disordinato) che poi ordini con un comparator (Collection.sort usa un merge sort).

Non vorrei aver detto una fesseria, magari attendi conferme, smentite o alternative in merito da altri utenti.

ok ho fatto esattamente quanto mi hai detto ed ha funzionato, ora le due versioni riportano esattamente gli stessi risultati.

Mi rimane la curiosità di capire come mai l'hashset ha deciso di restituirmi i risultati in ordine diverso così, a muzzo, visto che non ho cambiato ne dati ne funzione di hash...

banryu79
24-03-2010, 10:01
Mi rimane la curiosità di capire come mai l'hashset ha deciso di restituirmi i risultati in ordine diverso così, a muzzo, visto che non ho cambiato ne dati ne funzione di hash...

Non so il motivo specifico (nel senso che dovrei andare a spulciare i sorgenti di HashSet, o meglio di HashMap, dato che l'HashSet è implementato tramite una HashMap) ma, a te in quanto utente del Collection Framework dovrebbe bastarti ciò che viene dichiarato nei javadoc, cioè questo:

This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.

(map in questo contesto si riferisce alla HashMap interna all'HashSet)

Gold
24-03-2010, 11:47
Hashmap, posiziona gli elementi in base al loro hash e alla grandezza della tabella stessa.

Probabilmente le librerie che usi inizializzano il set a dimensioni diverse.

Saluto