Qual è il codice hash di un object se hashCode () non è sovrascritto?

Se il metodo hashCode () non è sovrascritto, quale sarà il risultato del richiamo di hashCode () su qualsiasi object in Java?

In genere, hashCode () restituisce semplicemente l’indirizzo dell’object in memoria se non lo si sovrascrive.

Dal 1 :

Per quanto ragionevolmente pratico, il metodo hashCode definito dalla class Object restituisce interi distinti per oggetti distinti. (Ciò viene in genere implementato convertendo l’indirizzo interno dell’object in un numero intero, ma questa tecnica di implementazione non è richiesta dal linguaggio di programmazione JavaTM.)

In HotSpot JVM per impostazione predefinita alla prima Object.hashCode o System.identityHashCode non sovraccarico viene generato e memorizzato un numero casuale nell’intestazione dell’object. Le conseguenti chiamate a Object.hashCode o System.identityHashCode estraggono semplicemente questo valore dall’intestazione. Di default non ha nulla in comune con il contenuto dell’object o la posizione dell’object, solo un numero casuale. Questo comportamento è controllato da -XX:hashCode=n Opzione JVM HotSpot che presenta i seguenti valori possibili:

  • 0: usa un generatore casuale globale. Questa è l’impostazione predefinita in Java 7. Ha lo svantaggio che le chiamate simultanee da più thread possono causare una condizione di competizione che genererà lo stesso hashCode per oggetti diversi. Anche in ritardi ambientali altamente concomitanti sono possibili a causa della contesa (utilizzando la stessa area di memoria da diversi core della CPU).
  • 5: usa un generatore casuale xor-shift thread-local che è libero dagli svantaggi precedenti. Questa è l’impostazione predefinita in Java 8.
  • 1: usa il puntatore dell’object mescolato con un valore casuale che viene modificato negli eventi “stop-the-world”, quindi tra gli eventi stop-the-world (come la garbage collection) gli hashCode generati sono stabili (a scopo di test / debugging)
  • 2: usa sempre 1 (per scopi di test / debugging)
  • 3: usa numeri autoincrementanti (per scopi di test / debug, viene utilizzato anche il contatore globale, quindi sono possibili contese e condizioni di gara)
  • 4: usa il puntatore dell’object tagliato a 32 bit se necessario (per scopi di test / debug)

Si noti che anche se si imposta -XX:hashCode=4 , hashCode non punta sempre sull’indirizzo dell’object. L’object può essere spostato in seguito, ma hashCode rimarrà lo stesso. Anche gli indirizzi degli oggetti sono scarsamente distribuiti (se l’applicazione utilizza non tanta memoria, la maggior parte degli oggetti si troverà l’uno vicino all’altro), quindi si potrebbe finire con tabelle hash sbilanciate se si utilizza questa opzione.

L’implementazione di hashCode() può differire da una class all’altra, ma il contratto per hashCode() è molto specifico e dichiarato chiaramente ed esplicitamente in Javadocs :

Restituisce un valore di codice hash per l’object. Questo metodo è supportato a beneficio di hashtables come quelli forniti da java.util.Hashtable.

Il contratto generale di hashCode è:

  • Ogni volta che viene invocato sullo stesso object più di una volta durante l’esecuzione di un’applicazione Java, il metodo hashCode deve restituire costantemente lo stesso numero intero, a condizione che non vengano modificate le informazioni utilizzate nei confronti degli uguali sull’object. Questo numero intero non deve rimanere coerente da un’esecuzione di un’applicazione a un’altra esecuzione della stessa applicazione.
  • Se due oggetti sono uguali secondo il metodo equals (Object), quindi chiamare il metodo hashCode su ciascuno dei due oggetti deve produrre lo stesso risultato intero.
  • Non è necessario che se due oggetti non sono uguali secondo il metodo equals (java.lang.Object), allora chiamare il metodo hashCode su ciascuno dei due oggetti deve produrre risultati interi distinti. Tuttavia, il programmatore dovrebbe essere consapevole del fatto che la produzione di risultati interi distinti per oggetti non uguali può migliorare le prestazioni degli hashtables.

Per quanto ragionevolmente pratico, il metodo hashCode definito dalla class Object restituisce interi distinti per oggetti distinti. (Ciò viene in genere implementato convertendo l’indirizzo interno dell’object in un numero intero, ma questa tecnica di implementazione non è richiesta dal linguaggio di programmazione JavaTM.)

hashCode() è strettamente legato a equals() e se si esegue l’override di equals() , si dovrebbe anche eseguire l’override di hashCode() .

Se hashcode non è sovrascritto, chiamerai l’hashcode dell’object, ecco un estratto dal suo javadoc:

Per quanto ragionevolmente pratico, il metodo hashCode definito dalla class Object restituisce interi distinti per oggetti distinti. (Ciò viene in genere implementato convertendo l’indirizzo interno dell’object in un numero intero, ma questa tecnica di implementazione non è richiesta dal linguaggio di programmazione JavaTM.)

l’implementazione hashcode predefinita fornisce l’indirizzo interno dell’object in jvm, come numero intero a 32 bit. Pertanto, due diversi oggetti (in memoria) avranno hashcode diversi.

Questo è coerente con l’implementazione predefinita di uguali. Se si desidera eseguire l’override degli uguali per i propri oggetti, è necessario adattare hashCode in modo che siano coerenti.

Vedi http://www.ibm.com/developerworks/java/library/j-jtp05273.html per una buona panoramica.

Dovresti provare a implementare il codice hash in modo che oggetti diversi diano risultati diversi. Non penso che ci sia un modo standard per farlo.

Leggi questo articolo per alcune informazioni .

Un codice hash è utile per memorizzare un object in una raccolta, come un hashset. Consentendo a un object di definire un codice hash come qualcosa di unico, l’algoritmo di HashSet può funzionare in modo efficace.

L’object stesso usa l’indirizzo dell’object in memoria, che è molto particolare, ma potrebbe non essere molto utile se due oggetti diversi (ad esempio due stringhe identiche) dovrebbero essere considerati uguali, anche se sono duplicati in memoria.

Due oggetti con codice hash diverso non devono essere uguali per quanto riguarda gli uguali ()

a.hashCode() != b.hashCode() deve implicare !a.equals(b)

Tuttavia, due oggetti che non sono uguali rispetto a equals () possono avere lo stesso codice hash. La memorizzazione di questi oggetti in un set o in una mappa diventerà meno efficiente se molti oggetti hanno lo stesso codice hash.

Non è davvero una risposta, ma aggiungendo al mio commento precedente

non è ansible garantire che l’indirizzo interno dell’object rimanga invariato nella JVM, il cui garbage collector potrebbe spostarlo durante la compattazione dell’heap.

Ho provato a fare qualcosa di simile:

 public static void main(String[] args) { final Object object = new Object(); while (true) { int hash = object.hashCode(); int x = 0; Runtime r = Runtime.getRuntime(); List list = new LinkedList(); while (r.freeMemory() / (double) r.totalMemory() > 0.3) { Object p = new Object(); list.add(p); x += object.hashCode();//ensure optimizer or JIT won't remove this } System.out.println(x); list.clear(); r.gc(); if (object.hashCode() != hash) { System.out.println("Voila!"); break; } } } 

Ma l’hashcode in effetti non cambia … qualcuno può dirmi come il JDK di Sun implementa effettivamente Obect.hashcode?

restituisce il numero esadecimale a 6 cifre. Di solito è la posizione di memoria dello slot in cui è indirizzato l’object. Da un algoritmo per caso, immagino che JDK faccia doppio hashing (implementazione nativa) che è una delle migliori funzioni di hashing per l’indirizzamento aperto. Questo schema di hashing doppio riduce notevolmente la possibilità di collisioni.

Il seguente post darà un’idea di supporto –

Java: confusione di HashMap sulla gestione delle collisioni e il metodo get ()

Devi eseguire l’override di hashCode in ogni class che esegue l’override degli uguali. In caso contrario, si verificherà una violazione del contratto generale per Object.hashCode, che impedirà alla class di funzionare correttamente conjunction with all hash-based collection , including HashMap, HashSet, and Hashtable.